From 2ef1dd2089ad991f1d4897022f2d28c2eb130837 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Fri, 14 Jun 2019 15:47:43 -0400 Subject: highlighting --- src/client/views/pdf/PDFMenu.tsx | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'src/client/views/pdf/PDFMenu.tsx') diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index cc5c0b77b..a0230113b 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -3,6 +3,8 @@ import "./PDFMenu.scss"; import { observable } from "mobx"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; +import { emptyFunction } from "../../../Utils"; +import { Doc } from "../../../new_fields/Doc"; @observer export default class PDFMenu extends React.Component { @@ -10,6 +12,8 @@ export default class PDFMenu extends React.Component { @observable Top: number = 0; @observable Left: number = 0; + StartDrag: (e: PointerEvent) => void = emptyFunction; + Highlight: (d: Doc | undefined) => void = emptyFunction; constructor(props: Readonly<{}>) { super(props); @@ -17,11 +21,28 @@ export default class PDFMenu extends React.Component { PDFMenu.Instance = this; } + pointerDown = (e: React.PointerEvent) => { + document.removeEventListener("pointermove", this.StartDrag); + document.addEventListener("pointermove", this.StartDrag); + document.removeEventListener("pointerup", this.pointerUp) + document.addEventListener("pointerup", this.pointerUp) + + e.stopPropagation(); + e.preventDefault(); + } + + pointerUp = (e: PointerEvent) => { + document.removeEventListener("pointermove", this.StartDrag); + document.removeEventListener("pointerup", this.pointerUp); + e.stopPropagation(); + e.preventDefault(); + } + render() { return (
- - + +
) } -- cgit v1.2.3-70-g09d2 From b987e2edbf7befbe90fafbdee476ee3b6513cc50 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Fri, 14 Jun 2019 17:44:17 -0400 Subject: pinning things --- src/client/views/MainView.tsx | 3 +- src/client/views/pdf/PDFMenu.scss | 13 ++++- src/client/views/pdf/PDFMenu.tsx | 119 +++++++++++++++++++++++++++++++++++--- src/client/views/pdf/Page.tsx | 21 ++++--- 4 files changed, 137 insertions(+), 19 deletions(-) (limited to 'src/client/views/pdf/PDFMenu.tsx') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 384cd2860..29015995f 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -1,5 +1,5 @@ import { IconName, library } from '@fortawesome/fontawesome-svg-core'; -import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faRedoAlt, faTable, faTree, faUndoAlt, faBell, faCommentAlt } from '@fortawesome/free-solid-svg-icons'; +import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup, faPenNib, faThumbtack, faRedoAlt, faTable, faTree, faUndoAlt, faBell, faCommentAlt } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; @@ -92,6 +92,7 @@ export class MainView extends React.Component { library.add(faMusic); library.add(faTree); library.add(faCommentAlt); + library.add(faThumbtack); this.initEventListeners(); this.initAuthenticationRouters(); } diff --git a/src/client/views/pdf/PDFMenu.scss b/src/client/views/pdf/PDFMenu.scss index b84ebc12d..22868082a 100644 --- a/src/client/views/pdf/PDFMenu.scss +++ b/src/client/views/pdf/PDFMenu.scss @@ -1,18 +1,25 @@ .pdfMenu-cont { position: absolute; z-index: 10000; - width: 100px; - height: 30px; + height: 35px; background: #323232; box-shadow: 3px 3px 3px rgba(0, 0, 0, 0.25); - border-radius: 0px 4px 4px 4px; + border-radius: 0px 6px 6px 6px; overflow: hidden; + display: flex; .pdfMenu-button { background-color: transparent; + width: 35px; + height: 35px; } .pdfMenu-button:hover { background-color: #121212; } + + .pdfMenu-dragger { + height: 100%; + transition: width .2s; + } } \ No newline at end of file diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index a0230113b..d2a20fb6e 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -1,6 +1,6 @@ import React = require("react"); import "./PDFMenu.scss"; -import { observable } from "mobx"; +import { observable, action } from "mobx"; import { observer } from "mobx-react"; import { FontAwesomeIcon } from "@fortawesome/react-fontawesome"; import { emptyFunction } from "../../../Utils"; @@ -10,10 +10,18 @@ import { Doc } from "../../../new_fields/Doc"; export default class PDFMenu extends React.Component { static Instance: PDFMenu; - @observable Top: number = 0; - @observable Left: number = 0; + @observable private _top: number = 0; + @observable private _left: number = 0; + @observable private _opacity: number = 1; + @observable private _transition: string = "opacity 0.5s"; + @observable private _transitionDelay: string = ""; + @observable private _pinned: boolean = false; + StartDrag: (e: PointerEvent) => void = emptyFunction; Highlight: (d: Doc | undefined) => void = emptyFunction; + @observable Highlighting: boolean = false; + + private _timeout: NodeJS.Timeout | undefined; constructor(props: Readonly<{}>) { super(props); @@ -38,12 +46,109 @@ export default class PDFMenu extends React.Component { e.preventDefault(); } + @action + jumpTo = (x: number, y: number) => { + if (!this._pinned) { + this._transition = this._transitionDelay = ""; + this._opacity = 1; + this._left = x; + this._top = y; + } + } + + @action + fadeOut = (forceOut: boolean) => { + if (!this._pinned) { + if (this._opacity === 0.2) { + this._transition = "opacity 0.1s"; + this._transitionDelay = ""; + this._opacity = 0; + this._left = this._top = -300; + } + + if (forceOut) { + this._transition = ""; + this._transitionDelay = ""; + this._opacity = 0; + this._left = this._top = -300; + } + } + } + + @action + pointerLeave = (e: React.PointerEvent) => { + if (!this._pinned) { + this._transition = "opacity 0.5s"; + this._transitionDelay = "1s"; + this._opacity = 0.2; + setTimeout(() => this.fadeOut(false), 3000); + } + } + + @action + pointerEntered = (e: React.PointerEvent) => { + this._transition = "opacity 0.1s"; + this._transitionDelay = ""; + this._opacity = 1; + } + + @action + togglePin = (e: React.MouseEvent) => { + this._pinned = !this._pinned; + } + + @action + dragging = (e: PointerEvent) => { + this._left += e.movementX; + this._top += e.movementY; + + e.stopPropagation(); + e.preventDefault(); + } + + dragEnd = (e: PointerEvent) => { + document.removeEventListener("pointermove", this.dragging); + document.removeEventListener("pointerup", this.dragEnd); + e.stopPropagation(); + e.preventDefault(); + } + + dragStart = (e: React.PointerEvent) => { + document.removeEventListener("pointermove", this.dragging); + document.addEventListener("pointermove", this.dragging); + document.removeEventListener("pointerup", this.dragEnd); + document.addEventListener("pointerup", this.dragEnd); + + e.stopPropagation(); + e.preventDefault(); + } + + @action + highlightClicked = (e: React.MouseEvent) => { + if (!this._pinned) { + this.Highlight(undefined); + } + else { + this.Highlighting = !this.Highlighting; + this.Highlight(undefined); + } + } + render() { return ( -
- - -
+
+ + + +
+
) } } \ No newline at end of file diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 44c502a04..3bc3ac33c 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -132,6 +132,7 @@ export default class Page extends React.Component { } } + @action highlight = (targetDoc: Doc | undefined) => { // creates annotation documents for current highlights let annotationDoc = this.props.makeAnnotationDocuments(targetDoc); @@ -196,6 +197,7 @@ export default class Page extends React.Component { // document.addEventListener("pointerup", this.endDrag); } else if (e.button === 0) { + PDFMenu.Instance.fadeOut(true); let target: any = e.target; if (target && target.parentElement === this._textLayer.current) { e.stopPropagation(); @@ -304,25 +306,28 @@ export default class Page extends React.Component { } copy.className = this._marquee.current.className; this.props.createAnnotation(copy, this.props.page); - PDFMenu.Instance.StartDrag = this.startDrag; - PDFMenu.Instance.Highlight = this.highlight; this._marquee.current.style.opacity = "0"; } this._marqueeHeight = this._marqueeWidth = 0; - PDFMenu.Instance.Left = e.clientX; - PDFMenu.Instance.Top = e.clientY; + PDFMenu.Instance.jumpTo(e.clientX, e.clientY); } else { let sel = window.getSelection(); if (sel && sel.type === "Range") { - PDFMenu.Instance.StartDrag = this.startDrag; - PDFMenu.Instance.Highlight = this.highlight; this.createTextAnnotation(sel); - PDFMenu.Instance.Left = e.clientX; - PDFMenu.Instance.Top = e.clientY; + PDFMenu.Instance.jumpTo(e.clientX, e.clientY); } } + + + if (PDFMenu.Instance.Highlighting) { + this.highlight(undefined); + } + else { + PDFMenu.Instance.StartDrag = this.startDrag; + PDFMenu.Instance.Highlight = this.highlight; + } // let x = (e.clientX - boundingRect.left) * (current.offsetWidth / boundingRect.width); // let y = (e.clientY - boundingRect.top) * (current.offsetHeight / boundingRect.height); // if (this._marqueeing) { -- cgit v1.2.3-70-g09d2 From 747fdb6d26afabad067f3f8d98789bfc7ca44f8d Mon Sep 17 00:00:00 2001 From: yipstanley Date: Fri, 14 Jun 2019 18:11:41 -0400 Subject: small stuffs --- src/client/views/pdf/PDFMenu.tsx | 1 + src/client/views/pdf/PDFViewer.tsx | 13 +++++++------ src/client/views/pdf/Page.tsx | 13 ++++++++----- 3 files changed, 16 insertions(+), 11 deletions(-) (limited to 'src/client/views/pdf/PDFMenu.tsx') diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index d2a20fb6e..2ba875e42 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -95,6 +95,7 @@ export default class PDFMenu extends React.Component { @action togglePin = (e: React.MouseEvent) => { this._pinned = !this._pinned; + this.Highlighting = this._pinned === false; } @action diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index dee891ba6..55d15893a 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -21,6 +21,7 @@ import { DocumentView } from "../nodes/DocumentView"; import { DragManager } from "../../util/DragManager"; import { Dictionary } from "typescript-collections"; +export const scale = 2; interface IPDFViewerProps { url: string; loaded: (nw: number, nh: number, np: number) => void; @@ -156,10 +157,10 @@ class Viewer extends React.Component { this._savedAnnotations.forEach((key: number, value: HTMLDivElement[]) => { for (let anno of value) { let annoDoc = new Doc(); - 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); - if (anno.style.width) annoDoc.width = parseInt(anno.style.width); + if (anno.style.left) annoDoc.x = parseInt(anno.style.left) / scale; + if (anno.style.top) annoDoc.y = parseInt(anno.style.top) / scale; + if (anno.style.height) annoDoc.height = parseInt(anno.style.height) / scale; + if (anno.style.width) annoDoc.width = parseInt(anno.style.width) / scale; annoDoc.page = key; annoDoc.target = sourceDoc; annoDoc.type = AnnotationTypes.Region; @@ -572,7 +573,7 @@ class PinAnnotation extends React.Component {
{ render() { return (
+ style={{ top: this.props.y * scale, left: this.props.x * scale, width: this.props.width * scale, height: this.props.height * scale, pointerEvents: "all", backgroundColor: this._backgroundColor }}>
); } } \ No newline at end of file diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index 455e1d831..bd2cae749 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -13,9 +13,10 @@ import { emptyFunction } from "../../../Utils"; import { Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { listSpec } from "../../../new_fields/Schema"; import { menuBar } from "prosemirror-menu"; -import { AnnotationTypes } from "./PDFViewer"; +import { AnnotationTypes, PDFViewer, scale } from "./PDFViewer"; import PDFMenu from "./PDFMenu"; + interface IPageProps { pdf: Opt; name: string; @@ -28,7 +29,7 @@ interface IPageProps { sendAnnotations: (annotations: HTMLDivElement[], page: number) => void; receiveAnnotations: (page: number) => HTMLDivElement[] | undefined; createAnnotation: (div: HTMLDivElement, page: number) => void; - makeAnnotationDocuments: (doc: Doc | undefined) => Doc; + makeAnnotationDocuments: (doc: Doc | undefined, scale: number) => Doc; } @observer @@ -103,7 +104,6 @@ export default class Page extends React.Component { @action private renderPage = (page: Pdfjs.PDFPageProxy): void => { // lower scale = easier to read at small sizes, higher scale = easier to read at large sizes - let scale = 2; let viewport = page.getViewport(scale); let canvas = this._canvas.current; let textLayer = this._textLayer.current; @@ -135,7 +135,7 @@ export default class Page extends React.Component { @action highlight = (targetDoc?: Doc) => { // creates annotation documents for current highlights - let annotationDoc = this.props.makeAnnotationDocuments(targetDoc); + let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, scale); let targetAnnotations = Cast(this.props.parent.Document.annotations, listSpec(Doc)); if (targetAnnotations === undefined) { Doc.GetProto(this.props.parent.Document).annotations = new List([annotationDoc]); @@ -307,8 +307,11 @@ export default class Page extends React.Component { this._marquee.current.style.opacity = "0"; } + if (this._marqueeWidth > 10 || this._marqueeHeight > 10) { + PDFMenu.Instance.jumpTo(e.clientX, e.clientY); + } + this._marqueeHeight = this._marqueeWidth = 0; - PDFMenu.Instance.jumpTo(e.clientX, e.clientY); } else { let sel = window.getSelection(); -- cgit v1.2.3-70-g09d2 From d9fba98b4022d2be68f67d830f17fea79580d2c4 Mon Sep 17 00:00:00 2001 From: yipstanley Date: Fri, 14 Jun 2019 18:13:18 -0400 Subject: small --- src/client/views/pdf/PDFMenu.tsx | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'src/client/views/pdf/PDFMenu.tsx') diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index 2ba875e42..b0735f63b 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -95,7 +95,9 @@ export default class PDFMenu extends React.Component { @action togglePin = (e: React.MouseEvent) => { this._pinned = !this._pinned; - this.Highlighting = this._pinned === false; + if (!this._pinned) { + this.Highlighting = false; + } } @action -- cgit v1.2.3-70-g09d2 From 122607408882617235af255af84ce78828b7982f Mon Sep 17 00:00:00 2001 From: yipstanley Date: Mon, 17 Jun 2019 13:42:21 -0400 Subject: page sizes loaded --- src/client/views/pdf/PDFMenu.tsx | 6 +++--- src/client/views/pdf/PDFViewer.tsx | 30 +++++++++++++++++++++++++++--- src/client/views/pdf/Page.tsx | 8 ++++---- 3 files changed, 34 insertions(+), 10 deletions(-) (limited to 'src/client/views/pdf/PDFMenu.tsx') diff --git a/src/client/views/pdf/PDFMenu.tsx b/src/client/views/pdf/PDFMenu.tsx index b0735f63b..b44370e3d 100644 --- a/src/client/views/pdf/PDFMenu.tsx +++ b/src/client/views/pdf/PDFMenu.tsx @@ -18,7 +18,7 @@ export default class PDFMenu extends React.Component { @observable private _pinned: boolean = false; StartDrag: (e: PointerEvent) => void = emptyFunction; - Highlight: (d: Doc | undefined) => void = emptyFunction; + Highlight: (d: Doc | undefined, color: string | undefined) => void = emptyFunction; @observable Highlighting: boolean = false; private _timeout: NodeJS.Timeout | undefined; @@ -129,11 +129,11 @@ export default class PDFMenu extends React.Component { @action highlightClicked = (e: React.MouseEvent) => { if (!this._pinned) { - this.Highlight(undefined); + this.Highlight(undefined, "#f4f442"); } else { this.Highlighting = !this.Highlighting; - this.Highlight(undefined); + this.Highlight(undefined, "#f4f442"); } } diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 9becfb419..d74a16f3f 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -23,6 +23,7 @@ import { Dictionary } from "typescript-collections"; import * as rp from "request-promise"; import { restProperty } from "babel-types"; import { DocServer } from "../../DocServer"; +import { number } from "prop-types"; export const scale = 2; interface IPDFViewerProps { @@ -141,10 +142,33 @@ class Viewer extends React.Component { setTimeout(() => { // this.renderPages(this.startIndex, this.endIndex, true); - this.saveThumbnail(); + this.initialLoad(); }, 1000); } + @action + initialLoad = () => { + let pdf = this.props.pdf; + if (pdf) { + this._pageSizes = Array<{ width: number, height: number }>(pdf.numPages); + let rendered = 0; + for (let i = 0; i < pdf.numPages; i++) { + pdf.getPage(i + 1).then( + (page: Pdfjs.PDFPageProxy) => { + runInAction(() => { + this._pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale }; + }); + console.log(`page ${i} size retreieved`); + rendered++; + if (rendered === pdf!.numPages - 1) { + this.saveThumbnail(); + } + } + ); + } + } + } + private mainCont = (div: HTMLDivElement | null) => { if (this._dropDisposer) { this._dropDisposer(); @@ -186,7 +210,7 @@ class Viewer extends React.Component { drop = async (e: Event, de: DragManager.DropEvent) => { if (de.data instanceof DragManager.LinkDragData) { let sourceDoc = de.data.linkSourceDocument; - let destDoc = this.makeAnnotationDocument(sourceDoc); + let destDoc = this.makeAnnotationDocument(sourceDoc, 1, "red"); let targetAnnotations = DocListCast(this.props.parent.Document.annotations); if (targetAnnotations) { targetAnnotations.push(destDoc); @@ -392,7 +416,7 @@ class Viewer extends React.Component { let numPages = this.props.pdf ? this.props.pdf.numPages : 0; let index = 0; let currOffset = vOffset; - while (index < numPages && currOffset - (this._pageSizes[index] ? this._pageSizes[index].height : 792 * scale) > 0) { + while (index < this._pageSizes.length && currOffset - (this._pageSizes[index] ? this._pageSizes[index].height : 792 * scale) > 0) { currOffset -= this._pageSizes[index] ? this._pageSizes[index].height : this._pageSizes[0].height; index++; } diff --git a/src/client/views/pdf/Page.tsx b/src/client/views/pdf/Page.tsx index e706a0d5c..bb87ec9d4 100644 --- a/src/client/views/pdf/Page.tsx +++ b/src/client/views/pdf/Page.tsx @@ -133,9 +133,9 @@ export default class Page extends React.Component { } @action - highlight = (targetDoc?: Doc) => { + highlight = (targetDoc?: Doc, color: string = "red") => { // creates annotation documents for current highlights - let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, scale, "#f4f442"); + let annotationDoc = this.props.makeAnnotationDocuments(targetDoc, scale, color); let targetAnnotations = Cast(this.props.parent.Document.annotations, listSpec(Doc)); if (targetAnnotations === undefined) { Doc.GetProto(this.props.parent.Document).annotations = new List([annotationDoc]); @@ -162,7 +162,7 @@ export default class Page extends React.Component { // document that this annotation is linked to let targetDoc = Docs.TextDocument({ width: 200, height: 200, title: "New Annotation" }); targetDoc.targetPage = this.props.page; - let annotationDoc = this.highlight(targetDoc); + let annotationDoc = this.highlight(targetDoc, "red"); // create dragData and star tdrag let dragData = new DragManager.AnnotationDragData(thisDoc, annotationDoc, targetDoc); if (this._textLayer.current) { @@ -323,7 +323,7 @@ export default class Page extends React.Component { if (PDFMenu.Instance.Highlighting) { - this.highlight(undefined); + this.highlight(undefined, "#f4f442"); } else { PDFMenu.Instance.StartDrag = this.startDrag; -- cgit v1.2.3-70-g09d2