aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorbob <bcz@cs.brown.edu>2019-09-24 16:32:31 -0400
committerbob <bcz@cs.brown.edu>2019-09-24 16:32:31 -0400
commitc5ae3ee0f24b980ac6d9669aded7cd3d51047cb4 (patch)
treee9194246837dffdaafc9900a712ce438392bbf3c /src
parent87407e68556db6f0c8641baf6b6d6dba98e4bbc5 (diff)
fixed moving to not redraw objects. pdf changes started.
Diffstat (limited to 'src')
-rw-r--r--src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx260
-rw-r--r--src/client/views/nodes/CollectionFreeFormDocumentView.tsx16
-rw-r--r--src/client/views/nodes/PDFBox.scss12
-rw-r--r--src/client/views/nodes/PDFBox.tsx64
-rw-r--r--src/client/views/pdf/PDFViewer.scss7
-rw-r--r--src/client/views/pdf/PDFViewer.tsx184
6 files changed, 211 insertions, 332 deletions
diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
index 36e62842c..438529596 100644
--- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
+++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx
@@ -1,7 +1,7 @@
import { library } from "@fortawesome/fontawesome-svg-core";
import { faEye } from "@fortawesome/free-regular-svg-icons";
import { faBraille, faChalkboard, faCompass, faCompressArrowsAlt, faExpandArrowsAlt, faPaintBrush, faTable, faUpload } from "@fortawesome/free-solid-svg-icons";
-import { action, computed, IReactionDisposer, observable, reaction, trace } from "mobx";
+import { action, computed, IReactionDisposer, observable, reaction, trace, ObservableMap, untracked } from "mobx";
import { observer } from "mobx-react";
import { Doc, DocListCastAsync, Field, FieldResult, HeightSym, Opt, WidthSym, DocListCast } from "../../../../new_fields/Doc";
import { Id } from "../../../../new_fields/FieldSymbols";
@@ -60,6 +60,17 @@ export interface ViewDefBounds {
z?: number;
width: number;
height: number;
+ transition?: string;
+}
+
+interface PivotData {
+ type: string;
+ text: string;
+ x: number;
+ y: number;
+ width: number;
+ height: number;
+ fontSize: number;
}
export interface ViewDefResult {
@@ -67,116 +78,6 @@ export interface ViewDefResult {
bounds?: ViewDefBounds;
}
-export namespace PivotView {
-
- export interface PivotData {
- type: string;
- text: string;
- x: number;
- y: number;
- width: number;
- height: number;
- fontSize: number;
- }
-
- export const elements = (target: CollectionFreeFormView) => {
- let collection = target.Document;
- const field = StrCast(collection.pivotField) || "title";
- const width = NumCast(collection.pivotWidth) || 200;
- const groups = new Map<FieldResult<Field>, Doc[]>();
-
- for (const doc of target.childDocs) {
- const val = doc[field];
- if (val === undefined) continue;
-
- const l = groups.get(val);
- if (l) {
- l.push(doc);
- } else {
- groups.set(val, [doc]);
- }
- }
-
- let minSize = Infinity;
-
- groups.forEach((val, key) => minSize = Math.min(minSize, val.length));
-
- const numCols = NumCast(collection.pivotNumColumns) || Math.ceil(Math.sqrt(minSize));
- const fontSize = NumCast(collection.pivotFontSize);
-
- const docMap = new Map<Doc, ViewDefBounds>();
- const groupNames: PivotData[] = [];
-
- let x = 0;
- groups.forEach((val, key) => {
- let y = 0;
- let xCount = 0;
- groupNames.push({
- type: "text",
- text: String(key),
- x,
- y: width + 50,
- width: width * 1.25 * numCols,
- height: 100, fontSize: fontSize
- });
- for (const doc of val) {
- docMap.set(doc, {
- x: x + xCount * width * 1.25,
- y: -y,
- width,
- height: width
- });
- xCount++;
- if (xCount >= numCols) {
- xCount = 0;
- y += width * 1.25;
- }
- }
- x += width * 1.25 * (numCols + 1);
- });
-
- let elements = target.viewDefsToJSX(groupNames);
- let docViews = target.childDocs.reduce((prev, doc) => {
- let minim = BoolCast(doc.isMinimized);
- if (minim === undefined || !minim) {
- let defaultPosition = (): ViewDefBounds => {
- return {
- x: NumCast(doc.x),
- y: NumCast(doc.y),
- z: NumCast(doc.z),
- width: NumCast(doc.width),
- height: NumCast(doc.height)
- };
- };
- const pos = docMap.get(doc) || defaultPosition();
- prev.push({
- ele: <CollectionFreeFormDocumentView
- key={doc[Id]}
- x={pos.x}
- y={pos.y}
- width={pos.width}
- height={pos.height}
- transition={"transform 1s"}
- jitterRotation={NumCast(target.props.Document.jitterRotation)}
- {...target.getChildDocumentViewProps(doc)}
- />,
- bounds: {
- x: pos.x,
- y: pos.y,
- z: pos.z,
- width: NumCast(pos.width),
- height: NumCast(pos.height)
- }
- });
- }
- return prev;
- }, elements);
-
- return docViews;
- };
-
-}
-
type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof documentSchema, typeof positionSchema, typeof pageSchema]>;
const PanZoomDocument = makeInterface(panZoomSchema, documentSchema, positionSchema, pageSchema);
@@ -300,7 +201,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
let y = (z ? ypo : yp) - de.data.offset[1];
let dropX = NumCast(de.data.droppedDocuments[0].x);
let dropY = NumCast(de.data.droppedDocuments[0].y);
- de.data.droppedDocuments.forEach(d => {
+ de.data.droppedDocuments.forEach(action((d: Doc) => {
d.x = x + NumCast(d.x) - dropX;
d.y = y + NumCast(d.y) - dropY;
if (!NumCast(d.width)) {
@@ -312,7 +213,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
d.height = nw && nh ? nh / nw * NumCast(d.width) : 300;
}
this.bringToFront(d);
- });
+ }));
de.data.droppedDocuments.length === 1 && this.updateCluster(de.data.droppedDocuments[0]);
}
@@ -645,6 +546,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
getScale = () => this.Document.scale ? this.Document.scale : 1;
getChildDocumentViewProps(childLayout: Doc, childData?: Doc): DocumentViewProps {
+ trace();
return {
DataDoc: childData,
Document: childLayout,
@@ -742,9 +644,99 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
}
}
- @computed.struct
- get elements() {
- if (this.Document.usePivotLayout) return PivotView.elements(this);
+ lookupLayout = (doc: Doc, dataDoc?: Doc) => {
+ let data: any = undefined;
+ let compute = this.Document.usePivotLayout ? this.doPivotComputation.map : this._doComputation.map;
+ compute.forEach((value: any, key: { layout: Doc, data?: Doc }) => {
+ if (key.layout === doc && key.data === dataDoc) {
+ data = value;
+ }
+ });
+ return data ? { x: data.x, y: data.y, z: data.z, width: data.width, height: data.height, transition: data.transition } : undefined;
+ }
+
+ @computed get doPivotComputation() {
+ let layoutPoolData: Map<{ layout: Doc, data?: Doc }, any> = new Map();
+ const field = StrCast(this.props.Document.pivotField) || "title";
+ const width = NumCast(this.props.Document.pivotWidth) || 200;
+ const groups = new Map<FieldResult<Field>, Doc[]>();
+
+ for (const doc of this.childDocs) {
+ const val = doc[field];
+ if (val === undefined) continue;
+
+ const l = groups.get(val);
+ if (l) {
+ l.push(doc);
+ } else {
+ groups.set(val, [doc]);
+ }
+ }
+
+ let minSize = Infinity;
+
+ groups.forEach((val, key) => minSize = Math.min(minSize, val.length));
+
+ const numCols = NumCast(this.props.Document.pivotNumColumns) || Math.ceil(Math.sqrt(minSize));
+ const fontSize = NumCast(this.props.Document.pivotFontSize);
+
+ const docMap = new Map<Doc, ViewDefBounds>();
+ const groupNames: PivotData[] = [];
+
+ let x = 0;
+ groups.forEach((val, key) => {
+ let y = 0;
+ let xCount = 0;
+ groupNames.push({
+ type: "text",
+ text: String(key),
+ x,
+ y: width + 50,
+ width: width * 1.25 * numCols,
+ height: 100, fontSize: fontSize
+ });
+ for (const doc of val) {
+ docMap.set(doc, {
+ x: x + xCount * width * 1.25,
+ y: -y,
+ width,
+ height: width,
+ });
+ xCount++;
+ if (xCount >= numCols) {
+ xCount = 0;
+ y += width * 1.25;
+ }
+ }
+ x += width * 1.25 * (numCols + 1);
+ });
+
+ let elements = this.viewDefsToJSX(groupNames);
+ let pairs = this.childLayoutPairs;
+ pairs.map((pair, i) => {
+ let minim = BoolCast(pair.layout.isMinimized);
+ if (minim === undefined || !minim) {
+ let defaultPosition = (): ViewDefBounds => {
+ return {
+ x: NumCast(pair.layout.x),
+ y: NumCast(pair.layout.y),
+ z: NumCast(pair.layout.z),
+ width: NumCast(pair.layout.width),
+ height: NumCast(pair.layout.height),
+ transition: "transform 1s"
+ };
+ };
+ const pos = docMap.get(pair.layout) || defaultPosition();
+ layoutPoolData.set(pair, { transition: "transform 1s", ...pos });
+ }
+ });
+ return { map: layoutPoolData, elements: elements };
+ };
+
+
+ @computed
+ get _doComputation() {
+ let layoutPoolData: Map<{ layout: Doc, data?: Doc }, any> = new Map();
let curPage = FieldValue(this.Document.curPage, -1);
const initScript = this.Document.arrangeInit;
let state: any = undefined;
@@ -759,24 +751,40 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
elements = this.viewDefsToJSX(views);
}
}
- let docviews = pairs.reduce((prev, pair) => {
+ pairs.map((pair, i) => {
var page = NumCast(pair.layout.page, -1);
if (!pair.layout.isMinimized && ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1)) {
- const pos = this.getCalculatedPositions({ doc: pair.layout, index: prev.length, collection: this.Document, docs: pairs.map(pair => pair.layout), state });
+ const pos = this.getCalculatedPositions({ doc: pair.layout, index: i, collection: this.Document, docs: pairs.map(pair => pair.layout), state });
state = pos.state === undefined ? state : pos.state;
+ layoutPoolData.set(pair, pos);
+ }
+ });
+ return { map: layoutPoolData, elements: elements };
+ }
+
+ @computed
+ get doComputation() {
+ let dc = this.Document.usePivotLayout ? this.doPivotComputation : this._doComputation;
+ let curPage = FieldValue(this.Document.curPage, -1);
+ let pairs = this.childLayoutPairs;
+ let docviews = pairs.reduce((prev, pair) => {
+ var page = NumCast(pair.layout.page, -1);
+ if (!pair.layout.isMinimized && ((Math.abs(Math.round(page) - Math.round(curPage)) < 3) || page === -1)) {
prev.push({
- ele: <CollectionFreeFormDocumentView key={pair.layout[Id]}
+ ele: <CollectionFreeFormDocumentView key={pair.layout[Id]} dataProvider={this.lookupLayout}
ruleProvider={this.Document.isRuleProvider ? this.props.Document : this.props.ruleProvider}
- jitterRotation={NumCast(this.props.Document.jitterRotation)}
- transition={pos.transition} x={pos.x} y={pos.y} width={pos.width} height={pos.height}
- {...this.getChildDocumentViewProps(pair.layout, pair.data)} />,
- bounds: { x: pos.x || 0, y: pos.y || 0, z: pos.z, width: pos.width || 0, height: pos.height || 0 }
+ jitterRotation={NumCast(this.props.Document.jitterRotation)} {...this.getChildDocumentViewProps(pair.layout, pair.data)} />,
+ bounds: this.lookupLayout(pair.layout, pair.data)
});
}
return prev;
- }, elements);
+ }, dc.elements);
- return docviews;
+ return { map: dc.map, elements: docviews };
+ }
+ @computed.struct
+ get elements() {
+ return this.doComputation.elements;
}
@computed.struct
@@ -945,7 +953,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) {
<CollectionFreeFormViewPannableContents centeringShiftX={this.centeringShiftX} centeringShiftY={this.centeringShiftY}
easing={easing} zoomScaling={this.zoomScaling} panX={this.panX} panY={this.panY}>
<CollectionFreeFormLinksView {...this.props} key="freeformLinks">
- <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} AnnotationDocument={this.fieldExtensionDoc} inkFieldKey={this._inkKey} >
+ <InkingCanvas getScreenTransform={this.getTransform} Document={this.props.Document} AnnotationDocument={this.fieldExtensionDoc} inkFieldKey={"ink"} >
{this.childViews}
</InkingCanvas>
</CollectionFreeFormLinksView>
diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
index 9685f9bca..0d9ace473 100644
--- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
+++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx
@@ -12,6 +12,7 @@ import { Doc, WidthSym, HeightSym } from "../../../new_fields/Doc";
import { random } from "animejs";
export interface CollectionFreeFormDocumentViewProps extends DocumentViewProps {
+ dataProvider?: (doc: Doc, dataDoc?: Doc) => { x: number, y: number, width: number, height: number, z: number, transition?: string } | undefined
x?: number;
y?: number;
width?: number;
@@ -32,11 +33,12 @@ export const PositionDocument = makeInterface(documentSchema, positionSchema);
@observer
export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeFormDocumentViewProps, PositionDocument>(PositionDocument) {
_disposer: IReactionDisposer | undefined = undefined;
- @computed get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${random(-1, 1) * this.props.jitterRotation}deg)`; }
- @computed get X() { return this._animPos !== undefined ? this._animPos[0] : this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.Document.x || 0; }
- @computed get Y() { return this._animPos !== undefined ? this._animPos[1] : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.Document.y || 0; }
- @computed get width() { return this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.props.Document[WidthSym](); }
- @computed get height() { return this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.props.Document[HeightSym](); }
+ get transform() { return `scale(${this.props.ContentScaling()}) translate(${this.X}px, ${this.Y}px) rotate(${random(-1, 1) * this.props.jitterRotation}deg)`; }
+ get X() { return this._animPos !== undefined ? this._animPos[0] : this.renderScriptDim ? this.renderScriptDim.x : this.props.x !== undefined ? this.props.x : this.dataProvider ? this.dataProvider.x : this.Document.x || 0; }
+ get Y() { return this._animPos !== undefined ? this._animPos[1] : this.renderScriptDim ? this.renderScriptDim.y : this.props.y !== undefined ? this.props.y : this.dataProvider ? this.dataProvider.y : this.Document.y || 0; }
+ get width() { return this.renderScriptDim ? this.renderScriptDim.width : this.props.width !== undefined ? this.props.width : this.props.dataProvider && this.dataProvider ? this.dataProvider.width : this.props.Document[WidthSym](); }
+ get height() { return this.renderScriptDim ? this.renderScriptDim.height : this.props.height !== undefined ? this.props.height : this.props.dataProvider && this.dataProvider ? this.dataProvider.height : this.props.Document[HeightSym](); }
+ @computed get dataProvider() { return this.props.dataProvider && this.props.dataProvider(this.props.Document, this.props.DataDoc) ? this.props.dataProvider(this.props.Document, this.props.DataDoc) : undefined; }
@computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); }
@computed get nativeHeight() { return FieldValue(this.Document.nativeHeight, 0); }
@computed get scaleToOverridingWidth() { return this.width / FieldValue(this.Document.width, this.width); }
@@ -99,6 +101,8 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
@observable _animPos: number[] | undefined = undefined;
render() {
+ console.log("this.props =" + this.props.dataProvider);
+ trace();
return (
<div className="collectionFreeFormDocumentView-container"
style={{
@@ -110,7 +114,7 @@ export class CollectionFreeFormDocumentView extends DocComponent<CollectionFreeF
StrCast(this.layoutDoc.boxShadow, ""),
borderRadius: this.borderRounding(),
transform: this.transform,
- transition: this.Document.isAnimating !== undefined ? ".5s ease-in" : this.props.transition ? this.props.transition : StrCast(this.layoutDoc.transition),
+ transition: this.Document.isAnimating !== undefined ? ".5s ease-in" : this.props.transition ? this.props.transition : this.dataProvider ? this.dataProvider.transition : StrCast(this.layoutDoc.transition),
width: this.width,
height: this.height,
zIndex: this.Document.zIndex || 0,
diff --git a/src/client/views/nodes/PDFBox.scss b/src/client/views/nodes/PDFBox.scss
index c88a94c28..cbea47e20 100644
--- a/src/client/views/nodes/PDFBox.scss
+++ b/src/client/views/nodes/PDFBox.scss
@@ -5,9 +5,6 @@
height: 100%;
overflow-y: scroll;
overflow-x: hidden;
- .pdfBox-scrollHack {
- pointer-events: none;
- }
}
.pdfBox-cont {
@@ -22,10 +19,11 @@
.pdfBox-cont-interactive {
pointer-events: all;
- .pdfPage-textlayer {
- span {
- pointer-events: all !important;
- user-select: text;
+ .pdfViewer-text {
+ .textLayer {
+ span {
+ user-select: text;
+ }
}
}
}
diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx
index 764051d62..d15f2b82c 100644
--- a/src/client/views/nodes/PDFBox.tsx
+++ b/src/client/views/nodes/PDFBox.tsx
@@ -46,16 +46,12 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
componentDidMount() {
this.props.setPdfBox && this.props.setPdfBox(this);
- this.props.Document.curPage = ComputedField.MakeFunction("Math.floor(Number(this.panY) / Number(this.nativeHeight) + 1)");
+ this.props.Document.curPage = 1; // ComputedField.MakeFunction("Math.floor(Number(this.panY) / Number(this.nativeHeight) + 1)");
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
if (pdfUrl instanceof PdfField) {
Pdfjs.getDocument(pdfUrl.url.pathname).promise.then(pdf => runInAction(() => this._pdf = pdf));
}
- this._reactionDisposer = reaction(
- () => this.Document.panY,
- () => this._mainCont.current && this._mainCont.current.scrollTo({ top: this.Document.panY || 0, behavior: "auto" })
- );
}
componentWillUnmount() {
@@ -63,36 +59,36 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
public GetPage() {
- return Math.floor((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1;
+ return 1;//Math.floor((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1;
}
@action
public BackPage() {
- let cp = Math.ceil((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1;
- cp = cp - 1;
- if (cp > 0) {
- this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0);
- }
+ // let cp = Math.ceil((this.Document.panY || 0) / (this.Document.nativeHeight || 0)) + 1;
+ // cp = cp - 1;
+ // if (cp > 0) {
+ // this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0);
+ // }
}
@action
public GotoPage = (p: number) => {
- if (p > 0 && p <= NumCast(this.dataDoc.numPages)) {
- this.Document.panY = (p - 1) * (this.Document.nativeHeight || 0);
- }
+ // if (p > 0 && p <= NumCast(this.dataDoc.numPages)) {
+ // this.Document.panY = (p - 1) * (this.Document.nativeHeight || 0);
+ // }
}
@action
public ForwardPage() {
- let cp = this.GetPage() + 1;
- if (cp <= NumCast(this.dataDoc.numPages)) {
- this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0);
- }
+ // let cp = this.GetPage() + 1;
+ // if (cp <= NumCast(this.dataDoc.numPages)) {
+ // this.Document.panY = (cp - 1) * (this.Document.nativeHeight || 0);
+ // }
}
@action
setPanY = (y: number) => {
- this.Document.panY = y;
+ //this.Document.panY = y;
}
@action
@@ -120,8 +116,7 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
settingsPanel() {
return !this.props.active() ? (null) :
(<div className="pdfBox-settingsCont" onPointerDown={(e) => e.stopPropagation()}>
- <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings"
- style={{ marginTop: `${this.Document.panY || 0}px` }}>
+ <button className="pdfBox-settingsButton" onClick={action(() => this._flyout = !this._flyout)} title="Open Annotation Settings" >
<div className="pdfBox-settingsButton-arrow"
style={{
borderTop: `25px solid ${this._flyout ? "#121721" : "transparent"}`,
@@ -161,38 +156,31 @@ export class PDFBox extends DocComponent<FieldViewProps, PdfDocument>(PdfDocumen
}
loaded = (nw: number, nh: number, np: number) => {
+ // nh *= .33.33333;
+ // nw *= 1.33333;
this.dataDoc.numPages = np;
if (!this.Document.nativeWidth || !this.Document.nativeHeight || !this.Document.scrollHeight) {
let oldaspect = (this.Document.nativeHeight || 0) / (this.Document.nativeWidth || 1);
this.Document.nativeWidth = nw;
this.Document.nativeHeight = this.Document.nativeHeight ? nw * oldaspect : nh;
this.Document.height = this.Document[WidthSym]() * (nh / nw);
- this.Document.scrollHeight = np * this.Document.nativeHeight;
- }
- }
-
- @action
- onScroll = (e: React.UIEvent<HTMLDivElement>) => {
- if (e.currentTarget && this.props.ContainingCollectionDoc) {
- this.props.Document.panTransformType = "None";
- this.Document.panY = e.currentTarget.scrollTop;
}
}
-
render() {
const pdfUrl = Cast(this.dataDoc[this.props.fieldKey], PdfField);
let classname = "pdfBox-cont" + (this.props.active() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : "");
return (!(pdfUrl instanceof PdfField) || !this._pdf ?
<div>{`pdf, ${this.dataDoc[this.props.fieldKey]}, not found`}</div> :
- <div className={classname}
- onScroll={this.onScroll}
- style={{ marginTop: `${(this.Document.panY || 0)}px` }}
- ref={this._mainCont}>
- <div className="pdfBox-scrollHack" style={{ height: NumCast(this.props.Document.scrollHeight) + ((this.Document.nativeHeight || 0) - (this.Document.nativeHeight || 0) / (this.Document.scale || 1)) }} />
- <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded} panY={this.Document.panY || 0}
+ <div className={classname} ref={this._mainCont} onWheel={(e: React.WheelEvent) => e.stopPropagation()} onPointerDown={(e: React.PointerEvent) => {
+ let hit = document.elementFromPoint(e.clientX, e.clientY);
+ if (hit && hit.localName === "span") {
+ e.button === 0 && e.stopPropagation();
+ }
+ }}>
+ <PDFViewer pdf={this._pdf} url={pdfUrl.url.pathname} active={this.props.active} scrollTo={this.scrollTo} loaded={this.loaded}
Document={this.props.Document} DataDoc={this.dataDoc}
- addDocTab={this.props.addDocTab} setPanY={this.setPanY} GoToPage={this.GotoPage}
+ addDocTab={this.props.addDocTab} GoToPage={this.GotoPage}
pinToPres={this.props.pinToPres} addDocument={this.props.addDocument}
fieldKey={this.props.fieldKey} fieldExtensionDoc={this.extensionDoc} />
{this.settingsPanel()}
diff --git a/src/client/views/pdf/PDFViewer.scss b/src/client/views/pdf/PDFViewer.scss
index a2f3911c5..fdfbde457 100644
--- a/src/client/views/pdf/PDFViewer.scss
+++ b/src/client/views/pdf/PDFViewer.scss
@@ -2,6 +2,9 @@
.pdfViewer-viewer {
pointer-events:inherit;
width: 100%;
+ height:100%;
+ position: absolute;
+ overflow: scroll;
.pdfViewer-visibleElements {
.pdfPage-cont {
.pdfPage-textLayer {
@@ -19,8 +22,10 @@
}
}
}
+ .page {
+ position: relative;
+ }
.pdfViewer-text {
- transform: scale(1.5);
transform-origin: top left;
}
diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx
index c94b4e3a4..4f1d3f07f 100644
--- a/src/client/views/pdf/PDFViewer.tsx
+++ b/src/client/views/pdf/PDFViewer.tsx
@@ -5,7 +5,7 @@ import * as Pdfjs from "pdfjs-dist";
import "pdfjs-dist/web/pdf_viewer.css";
import * as rp from "request-promise";
import { Dictionary } from "typescript-collections";
-import { Doc, DocListCast, FieldResult } from "../../../new_fields/Doc";
+import { Doc, DocListCast, FieldResult, WidthSym } from "../../../new_fields/Doc";
import { Id } from "../../../new_fields/FieldSymbols";
import { List } from "../../../new_fields/List";
import { ScriptField } from "../../../new_fields/ScriptField";
@@ -32,10 +32,8 @@ interface IViewerProps {
fieldExtensionDoc: Doc;
fieldKey: string;
loaded: (nw: number, nh: number, np: number) => void;
- panY: number;
scrollTo: (y: number) => void;
active: () => boolean;
- setPanY?: (n: number) => void;
GoToPage?: (n: number) => void;
addDocTab: (document: Doc, dataDoc: Doc | undefined, where: string) => boolean;
pinToPres: (document: Doc) => void;
@@ -47,16 +45,13 @@ interface IViewerProps {
*/
@observer
export class PDFViewer extends React.Component<IViewerProps> {
- @observable.shallow private _visibleElements: JSX.Element[] = []; // _visibleElements is the array of JSX elements that gets rendered
- @observable private _isPage: string[] = [];// _isPage is an array that tells us whether or not an index is rendered as a page or as a placeholder
- @observable private _pageSizes: { width: number, height: number }[] = [];
+ @observable public _pageSizes: { width: number, height: number }[] = [];
@observable private _annotations: Doc[] = [];
@observable private _savedAnnotations: Dictionary<number, HTMLDivElement[]> = new Dictionary<number, HTMLDivElement[]>();
@observable private _script: CompiledScript = CompileScript("return true") as CompiledScript;
@observable private _searching: boolean = false;
@observable private Index: number = -1;
- private _pageBuffer: number = 1;
private _annotationLayer: React.RefObject<HTMLDivElement> = React.createRef();
private _reactionDisposer?: IReactionDisposer;
private _annotationReactionDisposer?: IReactionDisposer;
@@ -68,16 +63,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
private _searchString: string = "";
private _selectionText: string = "";
- @computed get panY(): number { return this.props.panY; }
-
- // startIndex: where to start rendering pages
- @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.panY) - this._pageBuffer); }
-
- // endIndex: where to end rendering pages
- @computed get endIndex(): number {
- return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.panY + (this._pageSizes[0] ? this._pageSizes[0].height : 0)) + this._pageBuffer);
- }
-
@computed get allAnnotations() {
return DocListCast(this.props.fieldExtensionDoc.annotations).filter(
anno => this._script.run({ this: anno }, console.log, true).result);
@@ -87,16 +72,9 @@ export class PDFViewer extends React.Component<IViewerProps> {
return this._annotations.filter(anno => this._script.run({ this: anno }, console.log, true).result);
}
- componentDidUpdate = (prevProps: IViewerProps) => this.panY !== prevProps.panY && this.renderPages();
-
componentDidMount = async () => {
await this.initialLoad();
- this._reactionDisposer = reaction(
- () => [this.props.active(), this.startIndex, this._pageSizes.length ? this.endIndex : 0],
- () => this.renderPages(),
- { fireImmediately: true });
-
this._annotationReactionDisposer = reaction(
() => this.props.fieldExtensionDoc && DocListCast(this.props.fieldExtensionDoc.annotations),
annotations => annotations && annotations.length && this.renderAnnotations(annotations, true),
@@ -117,6 +95,8 @@ export class PDFViewer extends React.Component<IViewerProps> {
document.removeEventListener("copy", this.copy);
document.addEventListener("copy", this.copy);
+
+ setTimeout(() => this.toggleSearch(undefined as any), 1000);
}
componentWillUnmount = () => {
@@ -154,27 +134,16 @@ export class PDFViewer extends React.Component<IViewerProps> {
@action
initialLoad = async () => {
if (this._pageSizes.length === 0) {
- this._isPage = Array<string>(this.props.pdf.numPages);
this._pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages);
- this._visibleElements = Array<JSX.Element>(this.props.pdf.numPages);
await Promise.all(this._pageSizes.map<Pdfjs.PDFPromise<any>>((val, i) =>
this.props.pdf.getPage(i + 1).then(action((page: Pdfjs.PDFPageProxy) => {
this._pageSizes.splice(i, 1, {
- width: (page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]) * scale,
- height: (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]) * scale
+ width: (page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]),
+ height: (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0])
});
- this._visibleElements.splice(i, 1,
- <div key={`${this.props.url}-placeholder-${i + 1}`} className="pdfviewer-placeholder"
- style={{ width: this._pageSizes[i].width, height: this._pageSizes[i].height }}>
- "PAGE IS LOADING... "
- </div>);
- this.getPlaceholderPage(i);
+ i === this.props.pdf.numPages - 1 && this.props.loaded((page.view[page.rotate === 0 || page.rotate === 180 ? 2 : 3] - page.view[page.rotate === 0 || page.rotate === 180 ? 0 : 1]),
+ (page.view[page.rotate === 0 || page.rotate === 180 ? 3 : 2] - page.view[page.rotate === 0 || page.rotate === 180 ? 1 : 0]), i);
}))));
- this.props.loaded(Math.max(...this._pageSizes.map(i => i.width)), this._pageSizes[0].height, this.props.pdf.numPages);
-
- let startY = NumCast(this.props.Document.startY, NumCast(this.props.Document.panY));
- this.props.setPanY && this.props.setPanY(startY);
- this.props.scrollTo(startY);
}
}
@@ -231,61 +200,6 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
@action
- getPlaceholderPage = (page: number) => {
- if (this._isPage[page] !== "none") {
- this._isPage[page] = "none";
- this._visibleElements[page] = (
- <div key={`${this.props.url}-placeholder-${page + 1}`} className="pdfviewer-placeholder"
- style={{ width: this._pageSizes[page].width, height: this._pageSizes[page].height }}>
- "PAGE IS LOADING... "
- </div>);
- }
- }
-
- @action
- getRenderedPage = (page: number) => {
- if (this._isPage[page] !== "page") {
- this._isPage[page] = "page";
- this._visibleElements[page] = (<Page {...this.props}
- size={this._pageSizes[page]}
- numPages={this.props.pdf.numPages}
- setSelectionText={this.setSelectionText}
- page={page}
- key={`${this.props.url}-rendered-${page + 1}`}
- name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`}
- pageLoaded={this.pageLoaded}
- renderAnnotations={this.renderAnnotations}
- createAnnotation={this.createAnnotation}
- sendAnnotations={this.receiveAnnotations}
- makeAnnotationDocuments={this.makeAnnotationDocument}
- getScrollFromPage={this.getScrollFromPage} />);
- }
- }
-
- // change the address to be the file address of the PNG version of each page
- // file address of the pdf
- @action
- getPageImage = async (page: number) => {
- if (this._isPage[page] !== "image") {
- this._isPage[page] = "image";
- try {
- let res = JSON.parse(await rp.get(Utils.prepend(`/thumbnail${this.props.url.substring("files/".length, this.props.url.length - ".pdf".length)}-${page + 1}.PNG`)));
- runInAction(() => this._visibleElements[page] =
- <img key={res.path} src={res.path} onError={() => this.getRenderedPage(page)}
- style={{ width: `${parseInt(res.width) * scale}px`, height: `${parseInt(res.height) * scale}px` }} />);
- } catch (e) {
- console.log(e);
- }
- }
- }
-
- renderPages = () => {
- numberRange(this.props.pdf.numPages).filter(p => this._isPage[p] !== undefined).map(i =>
- (i < this.startIndex || i > this.endIndex) ? this.getPlaceholderPage(i) : // pages outside of the pdf use empty stand-in divs
- this.props.active() ? this.getRenderedPage(i) : this.getPageImage(i));
- }
-
- @action
renderAnnotations = (annotations: Doc[], removeOldAnnotations: boolean): void => {
if (removeOldAnnotations) {
this._annotations = annotations;
@@ -391,43 +305,44 @@ export class PDFViewer extends React.Component<IViewerProps> {
@action
toggleSearch = (e: React.MouseEvent) => {
- e.stopPropagation();
+ e && e.stopPropagation();
this._searching = !this._searching;
if (this._searching) {
if (!this._pdfFindController && this._mainCont.current && this._viewer.current && !this._pdfViewer) {
- let simpleLinkService = new SimpleLinkService(this);
+ document.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = this.props.Document[WidthSym]() / this._pageSizes[0].width);
+ document.addEventListener("pagerendered", () => console.log("rendered"));
+ var pdfLinkService = new PDFJSViewer.PDFLinkService();
+ this._pdfFindController = new PDFJSViewer.PDFFindController({
+ linkService: pdfLinkService,
+ });
this._pdfViewer = new PDFJSViewer.PDFViewer({
container: this._mainCont.current,
viewer: this._viewer.current,
- linkService: simpleLinkService
- })
- simpleLinkService.setPDFJSview(this._pdfViewer);
- this._mainCont.current.addEventListener("pagesinit", () => this._pdfViewer.currentScaleValue = 1);
- this._mainCont.current.addEventListener("pagerendered", () => console.log("rendered"));
+ linkService: pdfLinkService,
+ findController: this._pdfFindController,
+ renderer: "svg"
+ });
+ pdfLinkService.setViewer(this._pdfViewer);
+ pdfLinkService.setDocument(this.props.pdf, null);
this._pdfViewer.setDocument(this.props.pdf);
- this._pdfFindController = new PDFJSViewer.PDFFindController(this._pdfViewer);
- this._pdfViewer.findController = this._pdfFindController;
}
}
}
- @computed get visibleElementWrapper() {
- trace();
- return this._visibleElements;
- }
render() {
- return (<div className="pdfViewer-viewer" ref={this._mainCont} >
- <div className="pdfViewer-visibleElements" style={this._searching ? { position: "absolute", top: 0 } : {}}>
- {this.visibleElementWrapper}
+ trace();
+ let scaling = this._pageSizes.length && this._pageSizes[0] ? this._pageSizes[0].width / this.props.Document[WidthSym]() : 1;
+ return (<div className="pdfViewer-viewer" ref={this._mainCont} >
+ <div className="pdfViewer-text" key="viewerText" style={{ transform: `scale(${scaling})` }} >
+ <div key="viewerReal" ref={this._viewer} />
</div>
- <div className="pdfViewer-text" ref={this._viewer} />
<div className="pdfViewer-annotationLayer" style={{ height: NumCast(this.props.Document.nativeHeight) }} ref={this._annotationLayer}>
{this.nonDocAnnotations.sort((a, b) => NumCast(a.y) - NumCast(b.y)).map((anno, index) =>
<Annotation {...this.props} anno={anno} key={`${anno[Id]}-annotation`} />)}
</div>
<div className="pdfViewer-overlayCont" onPointerDown={(e) => e.stopPropagation()}
- style={{ bottom: -this.props.panY, left: `${this._searching ? 0 : 100}%` }}>
+ style={{ bottom: 0, left: `${this._searching ? 0 : 100}%` }}>
<button className="pdfViewer-overlayButton" title="Open Search Bar" />
<input className="pdfViewer-overlaySearchBar" placeholder="Search" onChange={this.searchStringChanged}
onKeyDown={(e: React.KeyboardEvent) => e.keyCode === KeyCodes.ENTER ? this.search(this._searchString) : e.keyCode === KeyCodes.BACKSPACE ? e.stopPropagation() : true} />
@@ -435,17 +350,17 @@ export class PDFViewer extends React.Component<IViewerProps> {
<FontAwesomeIcon icon="search" size="3x" color="white" /></button>
</div>
<button className="pdfViewer-overlayButton" onClick={this.prevAnnotation} title="Previous Annotation"
- style={{ bottom: -this.props.panY + 280, right: 10, display: this.props.active() ? "flex" : "none" }}>
+ style={{ bottom: 280, right: 10, display: this.props.active() ? "flex" : "none" }}>
<div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
<FontAwesomeIcon style={{ color: "white" }} icon={"arrow-up"} size="3x" /></div>
</button>
<button className="pdfViewer-overlayButton" onClick={this.nextAnnotation} title="Next Annotation"
- style={{ bottom: -this.props.panY + 200, right: 10, display: this.props.active() ? "flex" : "none" }}>
+ style={{ bottom: 200, right: 10, display: this.props.active() ? "flex" : "none" }}>
<div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
<FontAwesomeIcon style={{ color: "white" }} icon={"arrow-down"} size="3x" /></div>
</button>
<button className="pdfViewer-overlayButton" onClick={this.toggleSearch} title="Open Search Bar"
- style={{ bottom: -this.props.panY + 10, right: 0, display: this.props.active() ? "flex" : "none" }}>
+ style={{ bottom: 10, right: 0, display: this.props.active() ? "flex" : "none" }}>
<div className="pdfViewer-overlayButton-arrow" onPointerDown={(e) => e.stopPropagation()}></div>
<div className="pdfViewer-overlayButton-iconCont" onPointerDown={(e) => e.stopPropagation()}>
<FontAwesomeIcon style={{ color: "white" }} icon={this._searching ? "times" : "search"} size="3x" /></div>
@@ -455,42 +370,3 @@ export class PDFViewer extends React.Component<IViewerProps> {
}
export enum AnnotationTypes { Region }
-
-class SimpleLinkService {
- _viewer: PDFViewer;
- _pdfjsView: any;
-
- constructor(viewer: PDFViewer) {
- this._viewer = viewer;
- }
- setPDFJSview(v: any) { this._pdfjsView = v; }
-
- navigateTo() { }
-
- getDestinationHash() { return "#"; }
-
- getAnchorUrl() { return "#"; }
-
- setHash() { }
-
- isPageVisible(page: number) { return true; }
-
- executeNamedAction() { }
-
- cachePageRef() { }
-
- get pagesCount() { return this._viewer._pdfViewer.pagesCount; }
-
- get page() { return NumCast(this._viewer.props.Document.curPage); }
- set page(p: number) {
- this._pdfjsView._ensurePdfPageLoaded(this._pdfjsView._pages[p - 1]).then(() => {
- this._pdfjsView.renderingQueue.renderView(this._pdfjsView._pages[p - 1]);
- if (this._viewer.props.GoToPage)
- this._viewer.props.GoToPage(p);
- });
- }
-
-
- get rotation() { return 0; }
- set rotation(value: any) { }
-} \ No newline at end of file