aboutsummaryrefslogtreecommitdiff
path: root/src/client/views/pdf
diff options
context:
space:
mode:
Diffstat (limited to 'src/client/views/pdf')
-rw-r--r--src/client/views/pdf/PDFMenu.scss19
-rw-r--r--src/client/views/pdf/PDFMenu.tsx68
-rw-r--r--src/client/views/pdf/PDFViewer.tsx38
3 files changed, 98 insertions, 27 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.tsx b/src/client/views/pdf/PDFViewer.tsx
index 372d01b9c..4e5fdbfbb 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -97,7 +97,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
@observable private _zoomed = 1;
private _pdfViewer: any;
- private _retries = 0; // number of times tried to create the PDF viewer
+ private _retries = 0; // number of times tried to create the PDF viewer
private _setPreviewCursor: undefined | ((x: number, y: number, drag: boolean) => void);
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _reactionDisposer?: IReactionDisposer;
@@ -114,8 +114,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"]).
@@ -149,16 +149,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(), 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 => {
@@ -395,11 +390,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,
@@ -525,7 +521,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
if (this._marqueeing) {
if (this._marqueeWidth > 10 || this._marqueeHeight > 10) {
const marquees = this._mainCont.current!.getElementsByClassName("pdfViewerDash-dragAnnotationBox");
- if (marquees && marquees.length) { // copy the marquee and convert it to a permanent annotation.
+ if (marquees && marquees.length) { // copy the marquee and convert it to a permanent annotation.
const style = (marquees[0] as HTMLDivElement).style;
const copy = document.createElement("div");
copy.style.left = style.left;
@@ -695,7 +691,7 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
</div>;
}
@computed get pdfViewerDiv() {
- return <div className={"pdfViewerDash-text" + ((!DocumentDecorations.Instance.Interacting && (this.props.isSelected() || this.props.isChildActive())) ? "-selected" : "")} ref={this._viewer} />;
+ return <div className={"pdfViewerDash-text" + ((!DocumentDecorations.Instance?.Interacting && (this.props.isSelected() || this.props.isChildActive())) ? "-selected" : "")} ref={this._viewer} />;
}
@computed get contentScaling() { return this.props.ContentScaling(); }
@computed get standinViews() {
@@ -717,8 +713,8 @@ export class PDFViewer extends ViewBoxAnnotatableComponent<IViewerProps, PdfDocu
onScroll={this.onScroll} onWheel={this.onZoomWheel} onPointerDown={this.onPointerDown} onClick={this.onClick}
style={{
overflowX: this._zoomed !== 1 ? "scroll" : undefined,
- width: !this.props.Document._fitWidth ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`,
- height: !this.props.Document._fitWidth ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`,
+ width: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeWidth) : `${100 / this.contentScaling}%`,
+ height: !this.props.Document._fitWidth && (window.screen.width > 600) ? NumCast(this.props.Document._nativeHeight) : `${100 / this.contentScaling}%`,
transform: `scale(${this.props.ContentScaling()})`
}} >
{this.pdfViewerDiv}
@@ -750,4 +746,4 @@ class PdfViewerMarquee extends React.Component<PdfViewerMarqueeProps> {
}}>
</div>;
}
-} \ No newline at end of file
+}