From f74e512e500252ad76d77935e7aacbf72cb0dd9c Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 17 Jun 2019 14:41:21 -0400 Subject: added dropping on text as colleciton. --- src/client/views/TemplateMenu.tsx | 2 +- .../views/collections/CollectionSchemaView.tsx | 30 ++++++++++------------ .../views/collections/CollectionStackingView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 4 +-- src/client/views/nodes/FormattedTextBox.tsx | 28 ++++++++++++++++++-- 5 files changed, 44 insertions(+), 21 deletions(-) (limited to 'src/client') diff --git a/src/client/views/TemplateMenu.tsx b/src/client/views/TemplateMenu.tsx index 3288abd90..a9bc4d3d2 100644 --- a/src/client/views/TemplateMenu.tsx +++ b/src/client/views/TemplateMenu.tsx @@ -45,7 +45,7 @@ export class TemplateMenu extends React.Component { if (template.Name === "Bullet") { let topDocView = this.props.docs[0]; topDocView.addTemplate(template); - topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document.proto!)); + topDocView.props.Document.subBulletDocs = new List(this.props.docs.filter(v => v !== topDocView).map(v => v.props.Document)); } else { this.props.docs.map(d => d.addTemplate(template)); } diff --git a/src/client/views/collections/CollectionSchemaView.tsx b/src/client/views/collections/CollectionSchemaView.tsx index 7cc00ce07..4b46c73c1 100644 --- a/src/client/views/collections/CollectionSchemaView.tsx +++ b/src/client/views/collections/CollectionSchemaView.tsx @@ -2,36 +2,33 @@ import React = require("react"); import { library } from '@fortawesome/fontawesome-svg-core'; import { faCog, faPlus } from '@fortawesome/free-solid-svg-icons'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; -import { action, computed, observable, untracked, runInAction, trace } from "mobx"; +import { action, computed, observable, trace, untracked } from "mobx"; import { observer } from "mobx-react"; import ReactTable, { CellInfo, ComponentPropsGetterR, ReactTableDefaults } from "react-table"; -import { MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'; import "react-table/react-table.css"; +import { Doc, DocListCast, DocListCastAsync, Field } from "../../../new_fields/Doc"; +import { Id } from "../../../new_fields/FieldSymbols"; +import { List } from "../../../new_fields/List"; +import { listSpec } from "../../../new_fields/Schema"; +import { Cast, FieldValue, NumCast, StrCast } from "../../../new_fields/Types"; import { emptyFunction, returnFalse, returnZero } from "../../../Utils"; +import { Docs } from "../../documents/Documents"; +import { Gateway } from "../../northstar/manager/Gateway"; import { SetupDrag } from "../../util/DragManager"; import { CompileScript } from "../../util/Scripting"; import { Transform } from "../../util/Transform"; -import { COLLECTION_BORDER_WIDTH } from "../../views/globalCssVariables.scss"; +import { COLLECTION_BORDER_WIDTH, MAX_ROW_HEIGHT } from '../../views/globalCssVariables.scss'; +import { ContextMenu } from "../ContextMenu"; import { anchorPoints, Flyout } from "../DocumentDecorations"; import '../DocumentDecorations.scss'; import { EditableView } from "../EditableView"; import { DocumentView } from "../nodes/DocumentView"; import { FieldView, FieldViewProps } from "../nodes/FieldView"; +import { CollectionPDFView } from "./CollectionPDFView"; import "./CollectionSchemaView.scss"; import { CollectionSubView } from "./CollectionSubView"; -import { Opt, Field, Doc, DocListCastAsync, DocListCast } from "../../../new_fields/Doc"; -import { Cast, FieldValue, NumCast, StrCast, BoolCast } from "../../../new_fields/Types"; -import { listSpec } from "../../../new_fields/Schema"; -import { List } from "../../../new_fields/List"; -import { Id } from "../../../new_fields/FieldSymbols"; -import { Gateway } from "../../northstar/manager/Gateway"; -import { Docs } from "../../documents/Documents"; -import { ContextMenu } from "../ContextMenu"; -import { CollectionView } from "./CollectionView"; -import { CollectionPDFView } from "./CollectionPDFView"; import { CollectionVideoView } from "./CollectionVideoView"; -import { SelectionManager } from "../../util/SelectionManager"; -import { undoBatch } from "../../util/UndoManager"; +import { CollectionView } from "./CollectionView"; library.add(faCog); @@ -389,6 +386,7 @@ interface CollectionSchemaPreviewProps { CollectionView: CollectionView | CollectionPDFView | CollectionVideoView; getTransform: () => Transform; addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; + moveDocument: (document: Doc, target: Doc, addDoc: ((doc: Doc) => boolean)) => boolean; removeDocument: (document: Doc) => boolean; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; @@ -424,7 +422,7 @@ export class CollectionSchemaPreview extends React.Component doc) { getTransform={dxf} CollectionView={this.props.CollectionView} addDocument={this.props.addDocument} + moveDocument={this.props.moveDocument} removeDocument={this.props.removeDocument} active={this.props.active} whenActiveChanged={this.props.whenActiveChanged} diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 856fdab7f..8ece7d67f 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -285,8 +285,8 @@ export class DocumentView extends DocComponent(Docu let expandedProtoDocs = expandedDocs.map(doc => Doc.GetProto(doc)); let maxLocation = StrCast(this.props.Document.maximizeLocation, "inPlace"); let getDispDoc = (target: Doc) => Object.getOwnPropertyNames(target).indexOf("isPrototype") === -1 ? target : Doc.MakeDelegate(target); - if (altKey) { - maxLocation = this.props.Document.maximizeLocation = (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace"); + if (altKey || ctrlKey) { + maxLocation = this.props.Document.maximizeLocation = (ctrlKey ? maxLocation : (maxLocation === "inPlace" || !maxLocation ? "inTab" : "inPlace")); if (!maxLocation || maxLocation === "inPlace") { let hadView = expandedDocs.length === 1 && DocumentManager.Instance.getDocumentView(expandedProtoDocs[0], this.props.ContainingCollectionView); let wasMinimized = !hadView && expandedDocs.reduce((min, d) => !min && !BoolCast(d.IsMinimized, false), false); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index e5a43c60a..7a9593a60 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -8,10 +8,10 @@ import { keymap } from "prosemirror-keymap"; import { NodeType } from 'prosemirror-model'; import { EditorState, Plugin, Transaction } from "prosemirror-state"; import { EditorView } from "prosemirror-view"; -import { Doc, Opt } from "../../../new_fields/Doc"; +import { Doc, Opt, DocListCast } from "../../../new_fields/Doc"; import { Id } from '../../../new_fields/FieldSymbols'; import { RichTextField } from "../../../new_fields/RichTextField"; -import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; import { DocServer } from "../../DocServer"; import { Docs } from '../../documents/Documents'; @@ -30,6 +30,8 @@ import { InkingControl } from "../InkingControl"; import { FieldView, FieldViewProps } from "./FieldView"; import "./FormattedTextBox.scss"; import React = require("react"); +import { List } from '../../../new_fields/List'; +import { Templates } from '../Templates'; library.add(faEdit); library.add(faSmile); @@ -139,6 +141,28 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe let model: NodeType = (url.includes(".mov") || url.includes(".mp4")) ? schema.nodes.video : schema.nodes.image; this._editorView!.dispatch(this._editorView!.state.tr.insert(0, model.create({ src: url }))); e.stopPropagation(); + } else { + if (de.data instanceof DragManager.DocumentDragData) { + let ldocs = Cast(this.props.Document.subBulletDocs, listSpec(Doc)); + if (!ldocs) { + this.props.Document.subBulletDocs = new List([]); + } + ldocs = Cast(this.props.Document.subBulletDocs, listSpec(Doc)); + if (!ldocs) return; + if (!ldocs || !ldocs[0] || ldocs[0] instanceof Promise || StrCast((ldocs[0] as Doc).layout).indexOf("CollectionView") === -1) { + ldocs.splice(0, 0, Docs.StackingDocument([], { title: StrCast(this.props.Document.title) + "-subBullets", x: NumCast(this.props.Document.x), y: NumCast(this.props.Document.y) + NumCast(this.props.Document.height), width: 300, height: 300 })); + this.props.addDocument && this.props.addDocument(ldocs[0] as Doc); + this.props.Document.templates = new List([Templates.Bullet.Layout]); + this.props.Document.isBullet = true; + } + let stackDoc = (ldocs[0] as Doc); + if (de.data.moveDocument) { + de.data.moveDocument(de.data.draggedDocuments[0], stackDoc, (doc) => { + Cast(stackDoc.data, listSpec(Doc))!.push(doc); + return true; + }) + } + } } } -- cgit v1.2.3-70-g09d2 From 0cd0f5afdef91740fecdedaaecb2ed6be054eee5 Mon Sep 17 00:00:00 2001 From: bob Date: Mon, 17 Jun 2019 18:13:36 -0400 Subject: somewhat fixed problem of titles & text boxes --- src/client/views/MainOverlayTextBox.tsx | 4 ++++ src/client/views/Templates.tsx | 8 ++++---- 2 files changed, 8 insertions(+), 4 deletions(-) (limited to 'src/client') diff --git a/src/client/views/MainOverlayTextBox.tsx b/src/client/views/MainOverlayTextBox.tsx index 23e90ece5..4e983c906 100644 --- a/src/client/views/MainOverlayTextBox.tsx +++ b/src/client/views/MainOverlayTextBox.tsx @@ -10,6 +10,7 @@ import { Transform } from '../util/Transform'; import { CollectionDockingView } from './collections/CollectionDockingView'; import "./MainOverlayTextBox.scss"; import { FormattedTextBox } from './nodes/FormattedTextBox'; +import { For } from 'babel-types'; interface MainOverlayTextBoxProps { } @@ -25,6 +26,7 @@ export class MainOverlayTextBox extends React.Component private _textProxyDiv: React.RefObject; private _textBottom: boolean | undefined; private _textAutoHeight: boolean | undefined; + private _textBox: FormattedTextBox | undefined; @observable public TextDoc?: Doc; constructor(props: MainOverlayTextBoxProps) { @@ -33,6 +35,7 @@ export class MainOverlayTextBox extends React.Component MainOverlayTextBox.Instance = this; reaction(() => FormattedTextBox.InputBoxOverlay, (box?: FormattedTextBox) => { + this._textBox = box; if (box) { this.TextDoc = box.props.Document; let sxf = Utils.GetScreenTransform(box ? box.CurrentDiv : undefined); @@ -68,6 +71,7 @@ export class MainOverlayTextBox extends React.Component textScroll = (e: React.UIEvent) => { if (this._textProxyDiv.current && this._textTargetDiv) { this._textTargetDiv.scrollTop = (e as any)._targetInst.stateNode.scrollTop; + console.log(this._textTargetDiv.scrollTop + " != " + (e as any)._targetInst.stateNode.scrollTop + " != " + (this._textBox!.CurrentDiv ? this._textBox!.CurrentDiv.scrollTop : -1)); } } diff --git a/src/client/views/Templates.tsx b/src/client/views/Templates.tsx index 3cd525afa..3d5f7b6ea 100644 --- a/src/client/views/Templates.tsx +++ b/src/client/views/Templates.tsx @@ -48,12 +48,12 @@ export namespace Templates { ` ); export const Title = new Template("Title", TemplatePosition.InnerTop, - `
+ `
{props.Document.title}
-
-
{layout}
+
+
{layout}
` ); @@ -62,7 +62,7 @@ export namespace Templates {
-
{layout}
+
{layout}
` ); export const Bullet = new Template("Bullet", TemplatePosition.InnerTop, -- cgit v1.2.3-70-g09d2 From df05220570628c0f6f1f97329cd3719bb232ecd2 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 17 Jun 2019 19:09:36 -0400 Subject: from last --- src/client/views/nodes/DocumentView.scss | 1 + 1 file changed, 1 insertion(+) (limited to 'src/client') diff --git a/src/client/views/nodes/DocumentView.scss b/src/client/views/nodes/DocumentView.scss index 7c72fb6e6..3a4b46b7e 100644 --- a/src/client/views/nodes/DocumentView.scss +++ b/src/client/views/nodes/DocumentView.scss @@ -4,6 +4,7 @@ position: inherit; top: 0; left:0; + pointer-events: all; // background: $light-color; //overflow: hidden; transform-origin: left top; -- cgit v1.2.3-70-g09d2 From 71b1cfbebdc771440c1f3b1169611b5747450064 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Mon, 17 Jun 2019 20:09:12 -0400 Subject: changed default color picker --- src/client/views/MainView.tsx | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'src/client') diff --git a/src/client/views/MainView.tsx b/src/client/views/MainView.tsx index 29015995f..ea49ebd5d 100644 --- a/src/client/views/MainView.tsx +++ b/src/client/views/MainView.tsx @@ -3,7 +3,7 @@ import { faFilePdf, faFilm, faFont, faGlobeAsia, faImage, faMusic, faObjectGroup import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { action, computed, configure, observable, runInAction, trace } from 'mobx'; import { observer } from 'mobx-react'; -import { CirclePicker } from 'react-color'; +import { CirclePicker, SliderPicker, BlockPicker, TwitterPicker } from 'react-color'; import "normalize.css"; import * as React from 'react'; import Measure from 'react-measure'; @@ -230,6 +230,14 @@ export class MainView extends React.Component { return { fontSize: "50%" }; } + onColorClick = (e: React.MouseEvent) => { + let target = (e.nativeEvent! as any).path[0]; + let parent = (e.nativeEvent! as any).path[1]; + if (target.localName === "input" || parent.localName === "span") + e.stopPropagation(); + } + + @observable private _colorPickerDisplay = false; /* for the expandable add nodes menu. Not included with the miscbuttons because once it expands it expands the whole div with it, making canvas interactions limited. */ nodesMenu() { @@ -257,8 +265,8 @@ export class MainView extends React.Component {
  • {btns.map(btn => -- cgit v1.2.3-70-g09d2 From 8c64ffd92e382050bc8727981cf9fb830e4f02a7 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Mon, 17 Jun 2019 23:04:07 -0400 Subject: Added share with user functionality --- src/client/views/nodes/DocumentView.tsx | 48 +++++++++++++++++++++++++-------- src/client/views/nodes/FieldView.tsx | 2 +- src/server/RouteStore.ts | 1 + src/server/database.ts | 4 +-- src/server/index.ts | 11 ++++++++ 5 files changed, 52 insertions(+), 14 deletions(-) (limited to 'src/client') diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index 9d0206e48..942228e71 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,11 +1,11 @@ import { library } from '@fortawesome/fontawesome-svg-core'; import { faAlignCenter, faCaretSquareRight, faCompressArrowsAlt, faExpandArrowsAlt, faLayerGroup, faSquare, faTrash, faConciergeBell, faFolder, faMapPin, faLink, faFingerprint, faCrosshairs, faDesktop } from '@fortawesome/free-solid-svg-icons'; -import { action, computed, IReactionDisposer, reaction, trace, observable } from "mobx"; +import { action, computed, IReactionDisposer, reaction, trace, observable, runInAction } from "mobx"; import { observer } from "mobx-react"; import { Doc, DocListCast, HeightSym, Opt, WidthSym, DocListCastAsync } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; import { ObjectField } from "../../../new_fields/ObjectField"; -import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { createSchema, makeInterface, listSpec } from "../../../new_fields/Schema"; import { BoolCast, Cast, FieldValue, StrCast, NumCast, PromiseValue } from "../../../new_fields/Types"; import { CurrentUserUtils } from "../../../server/authentication/models/current_user_utils"; import { emptyFunction, Utils } from "../../../Utils"; @@ -26,10 +26,12 @@ import { DocComponent } from "../DocComponent"; import { PresentationView } from "../PresentationView"; import { Template } from "./../Templates"; import { DocumentContentsView } from "./DocumentContentsView"; +import * as rp from "request-promise"; import "./DocumentView.scss"; import React = require("react"); import { Id, Copy } from '../../../new_fields/FieldSymbols'; import { ContextMenuProps } from '../ContextMenuItem'; +import { RouteStore } from '../../../server/RouteStore'; const JsxParser = require('react-jsx-parser').default; //TODO Why does this need to be imported like this? library.add(faTrash); @@ -452,7 +454,8 @@ export class DocumentView extends DocComponent(Docu } @action - onContextMenu = (e: React.MouseEvent): void => { + onContextMenu = async (e: React.MouseEvent): Promise => { + e.persist(); e.stopPropagation(); if (Math.abs(this._downX - e.clientX) > 3 || Math.abs(this._downY - e.clientY) > 3 || e.isDefaultPrevented()) { @@ -483,14 +486,37 @@ export class DocumentView extends DocComponent(Docu cm.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])), icon: "link" }); cm.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]), icon: "fingerprint" }); cm.addItem({ description: "Delete", event: this.deleteClicked, icon: "trash" }); - if (!this.topMost) { - // DocumentViews should stop propagation of this event - e.stopPropagation(); - } - ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!SelectionManager.IsSelected(this)) { - SelectionManager.SelectDoc(this, false); - } + type User = { email: string, userDocumentId: string }; + const users: User[] = JSON.parse(await rp.get(DocServer.prepend(RouteStore.getUsers))); + let usersMenu: ContextMenuProps[] = users.filter(({ email }) => email !== CurrentUserUtils.email).map(({ email, userDocumentId }) => ({ + description: email, event: async () => { + const userDocument = await Cast(DocServer.GetRefField(userDocumentId), Doc); + if (!userDocument) { + throw new Error(`Couldn't get user document of user ${email}`); + } + const notifDoc = await Cast(userDocument.optionalRightCollection, Doc); + if (notifDoc instanceof Doc) { + const data = await Cast(notifDoc.data, listSpec(Doc)); + const sharedDoc = Doc.MakeAlias(this.props.Document); + if (data) { + data.push(sharedDoc); + } else { + notifDoc.data = new List([sharedDoc]); + } + } + } + })); + runInAction(() => { + cm.addItem({ description: "Share...", subitems: usersMenu }); + if (!this.topMost) { + // DocumentViews should stop propagation of this event + e.stopPropagation(); + } + ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); + if (!SelectionManager.IsSelected(this)) { + SelectionManager.SelectDoc(this, false); + } + }); } onPointerEnter = (e: React.PointerEvent): void => { this.props.Document.libraryBrush = true; }; diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index cf6d2012f..4738e90d7 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -109,7 +109,7 @@ export class FieldView extends React.Component { } else if (field instanceof List) { return (
    - {field.map(f => f instanceof Doc ? f.title : f.toString()).join(", ")} + {field.map(f => f instanceof Doc ? f.title : (f && f.toString && f.toString())).join(", ")}
    ); } // bcz: this belongs here, but it doesn't render well so taking it out for now diff --git a/src/server/RouteStore.ts b/src/server/RouteStore.ts index c4af5cdaa..5c13495ff 100644 --- a/src/server/RouteStore.ts +++ b/src/server/RouteStore.ts @@ -16,6 +16,7 @@ export enum RouteStore { // USER AND WORKSPACES getCurrUser = "/getCurrentUser", + getUsers = "/getUsers", getUserDocumentId = "/getUserDocumentId", updateCursor = "/updateCursor", diff --git a/src/server/database.ts b/src/server/database.ts index 70b3efced..d240bd909 100644 --- a/src/server/database.ts +++ b/src/server/database.ts @@ -120,9 +120,9 @@ export class Database { } } - public query(query: any): Promise { + public query(query: any, collectionName = "newDocuments"): Promise { if (this.db) { - return Promise.resolve(this.db.collection('newDocuments').find(query)); + return Promise.resolve(this.db.collection(collectionName).find(query)); } else { return new Promise(res => { this.onConnect.push(() => res(this.query(query))); diff --git a/src/server/index.ts b/src/server/index.ts index b91c91282..7ef542b01 100644 --- a/src/server/index.ts +++ b/src/server/index.ts @@ -203,6 +203,17 @@ addSecureRoute( RouteStore.root ); +addSecureRoute( + Method.GET, + async (_, res) => { + const cursor = await Database.Instance.query({}, "users"); + const results = await cursor.toArray(); + res.send(results.map(user => ({ email: user.email, userDocumentId: user.userDocumentId }))); + }, + undefined, + RouteStore.getUsers +); + addSecureRoute( Method.GET, (user, res, req) => { -- cgit v1.2.3-70-g09d2 From 4dc8c03562a0473becb895824740da487e16e771 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 18 Jun 2019 00:17:58 -0400 Subject: added dropping of Dash urls from gmail --- src/client/views/collections/CollectionSubView.tsx | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'src/client') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index b5a3d087e..af0495e4f 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -182,8 +182,19 @@ export function CollectionSubView(schemaCtor: (doc: Doc) => T) { return; } if (html && html.indexOf(" { + if (f instanceof Doc) { + if (options.x || options.y) { f.x = options.x; f.y = options.y; } // should be in CollectionFreeFormView + (f instanceof Doc) && this.props.addDocument(f, false); + } + }); + } else { + let htmlDoc = Docs.HtmlDocument(html, { ...options, width: 300, height: 300, documentText: text }); + this.props.addDocument(htmlDoc, false); + } return; } if (text && text.indexOf("www.youtube.com/watch") !== -1) { -- cgit v1.2.3-70-g09d2 From 62c781c0c79ac395c5e117d208a90485ff1ba599 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 18 Jun 2019 02:19:07 -0400 Subject: faster loading of PDFs --- src/client/views/nodes/PDFBox.tsx | 1 - src/client/views/pdf/PDFViewer.tsx | 340 +++++++++++++------------------------ 2 files changed, 116 insertions(+), 225 deletions(-) (limited to 'src/client') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 655c12ab3..3aaa5749d 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -69,7 +69,6 @@ export class PDFBox extends DocComponent(PdfDocumen loaded = (nw: number, nh: number, np: number) => { if (this.props.Document) { let doc = this.props.Document.proto ? this.props.Document.proto : this.props.Document; - console.log("pages = " + np); doc.numPages = np; if (doc.nativeWidth && doc.nativeHeight) return; let oldaspect = NumCast(doc.nativeHeight) / NumCast(doc.nativeWidth, 1); diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index d74a16f3f..5149e48fd 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -43,16 +43,7 @@ export class PDFViewer extends React.Component { @action componentDidMount() { - const pdfUrl = this.props.url; - console.log("pdf starting to load") - let promise = Pdfjs.getDocument(pdfUrl).promise; - - promise.then((pdf: Pdfjs.PDFDocumentProxy) => { - runInAction(() => { - console.log("pdf url received"); - this._pdf = pdf; - }); - }); + Pdfjs.getDocument(this.props.url).promise.then(pdf => runInAction(() => this._pdf = pdf)); } render() { @@ -83,12 +74,8 @@ class Viewer extends React.Component { // _visibleElements is the array of JSX elements that gets rendered @observable.shallow private _visibleElements: JSX.Element[] = []; // _isPage is an array that tells us whether or not an index is rendered as a page or as a placeholder - @observable private _isPage: boolean[] = []; + @observable private _isPage: string[] = []; @observable private _pageSizes: { width: number, height: number }[] = []; - @observable private _startIndex: number = 0; - @observable private _endIndex: number = 1; - @observable private _loaded: boolean = false; - @observable private _pdf: Opt; @observable private _annotations: Doc[] = []; @observable private _pointerEvents: "all" | "none" = "all"; @observable private _savedAnnotations: Dictionary = new Dictionary(); @@ -97,7 +84,6 @@ class Viewer extends React.Component { private _annotationLayer: React.RefObject; private _reactionDisposer?: IReactionDisposer; private _annotationReactionDisposer?: IReactionDisposer; - private _pagesLoaded: number = 0; private _dropDisposer?: DragManager.DragDropDisposer; constructor(props: IViewerProps) { @@ -106,77 +92,62 @@ class Viewer extends React.Component { this._annotationLayer = React.createRef(); } + componentDidUpdate = (prevProps: IViewerProps) => { + if (this.scrollY !== prevProps.scrollY && this._visibleElements.length) { + this.renderPages(this.startIndex, this.endIndex, false); + } + } + @action componentDidMount = () => { let wasSelected = this.props.parent.props.active(); - // reaction for when document gets (de)selected this._reactionDisposer = reaction( - () => [this.props.parent.props.active(), this.startIndex], - () => { - // if deselected, render images in place of pdf - if (wasSelected && !this.props.parent.props.active()) { - this.saveThumbnail(); - } - // if selected, render pdf - else if (!wasSelected && this.props.parent.props.active()) { - this.renderPages(this.startIndex, this.endIndex, true); - } + () => [this.props.parent.props.active(), this.startIndex, this.props.pdf], + async () => { + await this.initialLoad(); wasSelected = this.props.parent.props.active(); - this._pointerEvents = wasSelected ? "none" : "all"; - }, - { fireImmediately: true } - ); + runInAction(() => this._pointerEvents = wasSelected ? "none" : "all"); + this.renderPages(this.startIndex, this.endIndex, false); + }, { fireImmediately: true }); - if (this.props.parent.Document) { - this._annotationReactionDisposer = reaction( - () => DocListCast(this.props.parent.Document.annotations), - () => { - let annotations = DocListCast(this.props.parent.Document.annotations); - if (annotations && annotations.length) { - this.renderAnnotations(annotations, true); - } - }, - { fireImmediately: true } - ); - } + this._annotationReactionDisposer = reaction( + () => this.props.parent.Document && DocListCast(this.props.parent.Document.annotations), + (annotations: Doc[]) => + annotations && annotations.length && this.renderAnnotations(annotations, true), + { fireImmediately: true }); + } - setTimeout(() => { - // this.renderPages(this.startIndex, this.endIndex, true); - this.initialLoad(); - }, 1000); + componentWillUnmount = () => { + this._reactionDisposer && this._reactionDisposer(); + this._annotationReactionDisposer && this._annotationReactionDisposer(); } @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(); - } - } - ); + initialLoad = async () => { + if (this.props.pdf && this._pageSizes.length === 0) { + let pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages); + for (let i = 0; i < this.props.pdf.numPages; i++) { + await this.props.pdf.getPage(i + 1).then(page => runInAction(() => { + pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale }; + if (i === 0) this.props.loaded(pageSizes[i].width, pageSizes[i].height, this.props.pdf!.numPages); + })); } + runInAction(() => { + this._pageSizes = pageSizes; + let divs = Array.from(Array(this._pageSizes.length).keys()).map(i => ( +
    + )); + this._isPage = Array.from(Array(this._pageSizes.length).map(p => "none")); + this._visibleElements = new Array(...divs); + }) } } private mainCont = (div: HTMLDivElement | null) => { - if (this._dropDisposer) { - this._dropDisposer(); - } + this._dropDisposer && this._dropDisposer(); if (div) { - this._dropDisposer = DragManager.MakeDropTarget(div, { - handlers: { drop: this.drop.bind(this) } - }); + this._dropDisposer = div && DragManager.MakeDropTarget(div, { handlers: { drop: this.drop.bind(this) } }); } } @@ -222,154 +193,102 @@ class Viewer extends React.Component { e.stopPropagation(); } } - - componentWillUnmount = () => { - if (this._reactionDisposer) { - this._reactionDisposer(); - } - if (this._annotationReactionDisposer) { - this._annotationReactionDisposer(); - } - } - + /** + * Called by the Page class when it gets rendered, initializes the lists and + * puts a placeholder with all of the correct page sizes when all of the pages have been loaded. + */ @action - saveThumbnail = async () => { - // file address of the pdf - const address: string = this.props.url; - for (let i = 0; i < this._visibleElements.length; i++) { - if (this._isPage[i]) { - // change the address to be the file address of the PNG version of each page - let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${i + 1}.PNG`))); - let thisAddress = res.path; - let nWidth = parseInt(res.width); - let nHeight = parseInt(res.height); - // replace page with image - runInAction(() => - this._visibleElements[i] = ); - } - } - } - - @computed get scrollY(): number { - return this.props.scrollY; - } - - @computed get startIndex(): number { - return Math.max(0, this.getIndex(this.scrollY) - this._pageBuffer); - } - - @computed get endIndex(): number { - let width = this._pageSizes.map(i => i ? i.width : 0); - return Math.min(this.props.pdf ? this.props.pdf.numPages - 1 : 0, this.getIndex(this.scrollY + Math.max(...width)) + this._pageBuffer); - } - - componentDidUpdate = (prevProps: IViewerProps) => { - if (this.scrollY !== prevProps.scrollY || this._pdf !== this.props.pdf) { - this._pdf = this.props.pdf; - // render pages if the scorll position changes - console.log(`START: ${this.startIndex}, END: ${this.endIndex}`); - this.renderPages(this.startIndex, this.endIndex); - } + pageLoaded = (index: number, page: Pdfjs.PDFPageViewport): void => { + this.props.pdf && this.props.loaded && this.props.loaded(page.width, page.height, this.props.pdf.numPages); } - @action - private renderAnnotations = (annotations: Doc[], removeOldAnnotations: boolean): void => { - if (removeOldAnnotations) { - this._annotations = annotations; - } - else { - this._annotations.push(...annotations); - this._annotations = new Array(...this._annotations); + getPlaceholderPage = (page: number) => { + if (this._isPage[page] !== "none") { + this._isPage[page] = "none"; + this._visibleElements[page] = ( +
    + ); } } - - /** - * @param startIndex: where to start rendering pages - * @param endIndex: where to end rendering pages - * @param forceRender: (optional), force pdfs to re-render, even if the page already exists - */ @action - renderPages = (startIndex: number, endIndex: number, forceRender: boolean = false) => { - let numPages = this.props.pdf ? this.props.pdf.numPages : 0; - if (!this.props.pdf) { - return; - } - - if (this._pageSizes.length !== numPages) { - this._pageSizes = new Array(numPages).map(i => ({ width: 0, height: 0 })); - } - - // this is only for an initial render to get all of the pages rendered - if (this._visibleElements.length !== numPages) { - let divs = Array.from(Array(numPages).keys()).map(i => i < 5 ? ( + getRenderedPage = (page: number) => { + if (this._isPage[page] !== "page") { + this._isPage[page] = "page"; + this._visibleElements[page] = ( - ) : - (
    ) ); - let arr = Array.from(Array(numPages).keys()).map(i => i < 5); - this._visibleElements.push(...divs); - this._isPage.push(...arr); } + } - // if nothing changed, return - if (startIndex === this._startIndex && endIndex === this._endIndex && !forceRender) { - return; + // 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) => { + let handleError = () => this.getRenderedPage(page); + if (this._isPage[page] != "image") { + this._isPage[page] = "image"; + const address = this.props.url; + let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`))); + runInAction(() => this._visibleElements[page] = ); } + } - // unrender pages outside of the pdf by replacing them with empty stand-in divs - for (let i = 0; i < numPages; i++) { - if (i < startIndex || i > endIndex) { - if (this._isPage[i]) { - this._visibleElements[i] = ( -
    - ); + @computed get scrollY(): number { return this.props.scrollY; } + + @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.scrollY) - this._pageBuffer); } + + @computed get endIndex(): number { + let width = this._pageSizes.map(i => i ? i.width : 0); + return Math.min(this.props.pdf ? this.props.pdf.numPages - 1 : 0, this.getPageFromScroll(this.scrollY + Math.max(...width)) + this._pageBuffer); + } + + /** + * @param startIndex: where to start rendering pages + * @param endIndex: where to end rendering pages + * @param forceRender: (optional), force pdfs to re-render, even if the page already exists + */ + @action + renderPages = (startIndex: number, endIndex: number, forceRender: boolean = false) => { + if (this.props.pdf) { + // unrender pages outside of the pdf by replacing them with empty stand-in divs + for (let i = 0; i < this.props.pdf.numPages; i++) { + if (i < startIndex || i > endIndex) { + this.getPlaceholderPage(i); + } else { + if (this.props.parent.props.active()) { + this.getRenderedPage(i); + } else { + this.getPageImage(i); + } } - this._isPage[i] = false; } } + } - // render pages for any indices that don't already have pages (force rerender will make these render regardless) - for (let i = startIndex; i <= endIndex; i++) { - if (!this._isPage[i] || (this._isPage[i] && forceRender)) { - this._visibleElements[i] = ( - - ); - this._isPage[i] = true; - } + @action + private renderAnnotations = (annotations: Doc[], removeOldAnnotations: boolean): void => { + if (removeOldAnnotations) { + this._annotations = annotations; + } + else { + this._annotations.push(...annotations); + this._annotations = new Array(...this._annotations); } - - this._startIndex = startIndex; - this._endIndex = endIndex; - - return; } @action @@ -392,7 +311,7 @@ class Viewer extends React.Component { let pinAnno = new Doc(); pinAnno.x = x; - pinAnno.y = y + this.getPageHeight(page); + pinAnno.y = y + this.getScrollFromPage(page); pinAnno.width = pinAnno.height = PinRadius; pinAnno.page = page; pinAnno.target = targetDoc; @@ -411,9 +330,7 @@ class Viewer extends React.Component { } // get the page index that the vertical offset passed in is on - getIndex = (vOffset: number) => { - // if (this._loaded) { - let numPages = this.props.pdf ? this.props.pdf.numPages : 0; + getPageFromScroll = (vOffset: number) => { let index = 0; let currOffset = vOffset; while (index < this._pageSizes.length && currOffset - (this._pageSizes[index] ? this._pageSizes[index].height : 792 * scale) > 0) { @@ -421,34 +338,10 @@ class Viewer extends React.Component { index++; } return index; - // } - return 0; } - /** - * Called by the Page class when it gets rendered, initializes the lists and - * puts a placeholder with all of the correct page sizes when all of the pages have been loaded. - */ - @action - pageLoaded = (index: number, page: Pdfjs.PDFPageViewport): void => { - if (this._loaded) { - return; - } - let numPages = this.props.pdf ? this.props.pdf.numPages : 0; - this.props.loaded(page.width, page.height, numPages); - this._pageSizes[index - 1] = { width: page.width, height: page.height }; - this._pagesLoaded++; - if (this._pagesLoaded === numPages) { - this._loaded = true; - let divs = Array.from(Array(numPages).keys()).map(i => ( -
    - )); - this._visibleElements = new Array(...divs); - this.renderPages(this.startIndex, this.endIndex, true); - } - } - getPageHeight = (index: number): number => { + getScrollFromPage = (index: number): number => { let counter = 0; if (this.props.pdf && index < this.props.pdf.numPages) { for (let i = 0; i < index; i++) { @@ -463,7 +356,7 @@ class Viewer extends React.Component { createAnnotation = (div: HTMLDivElement, page: number) => { if (this._annotationLayer.current) { if (div.style.top) { - div.style.top = (parseInt(div.style.top) + this.getPageHeight(page)).toString(); + div.style.top = (parseInt(div.style.top) + this.getScrollFromPage(page)).toString(); } this._annotationLayer.current.append(div); let savedPage = this._savedAnnotations.getValue(page); @@ -494,7 +387,6 @@ class Viewer extends React.Component { } render() { - trace(); return (
    -- cgit v1.2.3-70-g09d2 From 2f5c38c6a0a5220c2a31931c34d94e199854d703 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 18 Jun 2019 08:36:37 -0400 Subject: more streamlining --- src/client/views/pdf/PDFViewer.tsx | 144 +++++++++++++++---------------------- 1 file changed, 57 insertions(+), 87 deletions(-) (limited to 'src/client') diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 5149e48fd..645afc636 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -1,29 +1,23 @@ +import { action, computed, IReactionDisposer, observable, reaction, runInAction } from "mobx"; import { observer } from "mobx-react"; -import React = require("react"); -import { observable, action, runInAction, computed, IReactionDisposer, reaction, trace } from "mobx"; import * as Pdfjs from "pdfjs-dist"; -import { Opt, HeightSym, WidthSym, Doc, DocListCast } from "../../../new_fields/Doc"; -import "./PDFViewer.scss"; import "pdfjs-dist/web/pdf_viewer.css"; -import { PDFBox } from "../nodes/PDFBox"; -import Page from "./Page"; -import { NumCast, Cast, BoolCast, StrCast } from "../../../new_fields/Types"; +import * as rp from "request-promise"; +import { Dictionary } from "typescript-collections"; +import { Doc, DocListCast, HeightSym, Opt, WidthSym } from "../../../new_fields/Doc"; import { Id } from "../../../new_fields/FieldSymbols"; -import { DocUtils, Docs } from "../../documents/Documents"; -import { DocumentManager } from "../../util/DocumentManager"; -import { SelectionManager } from "../../util/SelectionManager"; import { List } from "../../../new_fields/List"; -import { DocumentContentsView } from "../nodes/DocumentContentsView"; -import { CollectionFreeFormDocumentView } from "../nodes/CollectionFreeFormDocumentView"; -import { Transform } from "../../util/Transform"; -import { emptyFunction, returnTrue, returnFalse } from "../../../Utils"; -import { DocumentView } from "../nodes/DocumentView"; -import { DragManager } from "../../util/DragManager"; -import { Dictionary } from "typescript-collections"; -import * as rp from "request-promise"; -import { restProperty } from "babel-types"; +import { BoolCast, Cast, NumCast, StrCast } from "../../../new_fields/Types"; +import { emptyFunction } from "../../../Utils"; import { DocServer } from "../../DocServer"; -import { number } from "prop-types"; +import { Docs, DocUtils } from "../../documents/Documents"; +import { DocumentManager } from "../../util/DocumentManager"; +import { DragManager } from "../../util/DragManager"; +import { DocumentView } from "../nodes/DocumentView"; +import { PDFBox } from "../nodes/PDFBox"; +import Page from "./Page"; +import "./PDFViewer.scss"; +import React = require("react"); export const scale = 2; interface IPDFViewerProps { @@ -49,14 +43,15 @@ export class PDFViewer extends React.Component { render() { return (
    - + {!this._pdf ? (null) : + }
    ); } } interface IViewerProps { - pdf: Opt; + pdf: Pdfjs.PDFDocumentProxy; loaded: (nw: number, nh: number, np: number) => void; scrollY: number; parent: PDFBox; @@ -77,37 +72,27 @@ class Viewer extends React.Component { @observable private _isPage: string[] = []; @observable private _pageSizes: { width: number, height: number }[] = []; @observable private _annotations: Doc[] = []; - @observable private _pointerEvents: "all" | "none" = "all"; @observable private _savedAnnotations: Dictionary = new Dictionary(); private _pageBuffer: number = 1; - private _annotationLayer: React.RefObject; + private _annotationLayer: React.RefObject = React.createRef(); private _reactionDisposer?: IReactionDisposer; private _annotationReactionDisposer?: IReactionDisposer; private _dropDisposer?: DragManager.DragDropDisposer; - constructor(props: IViewerProps) { - super(props); - - this._annotationLayer = React.createRef(); - } - componentDidUpdate = (prevProps: IViewerProps) => { - if (this.scrollY !== prevProps.scrollY && this._visibleElements.length) { - this.renderPages(this.startIndex, this.endIndex, false); + if (this.scrollY !== prevProps.scrollY) { + this.renderPages(); } } @action componentDidMount = () => { - let wasSelected = this.props.parent.props.active(); this._reactionDisposer = reaction( - () => [this.props.parent.props.active(), this.startIndex, this.props.pdf], + () => [this.props.parent.props.active(), this.startIndex, this.endIndex], async () => { await this.initialLoad(); - wasSelected = this.props.parent.props.active(); - runInAction(() => this._pointerEvents = wasSelected ? "none" : "all"); - this.renderPages(this.startIndex, this.endIndex, false); + this.renderPages(); }, { fireImmediately: true }); this._annotationReactionDisposer = reaction( @@ -124,23 +109,15 @@ class Viewer extends React.Component { @action initialLoad = async () => { - if (this.props.pdf && this._pageSizes.length === 0) { + if (this._pageSizes.length === 0) { let pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages); for (let i = 0; i < this.props.pdf.numPages; i++) { - await this.props.pdf.getPage(i + 1).then(page => runInAction(() => { - pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale }; - if (i === 0) this.props.loaded(pageSizes[i].width, pageSizes[i].height, this.props.pdf!.numPages); - })); + await this.props.pdf.getPage(i + 1).then(page => runInAction(() => + pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale })); } - runInAction(() => { - this._pageSizes = pageSizes; - let divs = Array.from(Array(this._pageSizes.length).keys()).map(i => ( -
    - )); - this._isPage = Array.from(Array(this._pageSizes.length).map(p => "none")); - this._visibleElements = new Array(...divs); - }) + this.props.loaded(pageSizes[0].width, pageSizes[0].height, this.props.pdf.numPages); + runInAction(() => + Array.from(Array((this._pageSizes = pageSizes).length).keys()).map(this.getPlaceholderPage)) } } @@ -199,14 +176,15 @@ class Viewer extends React.Component { */ @action pageLoaded = (index: number, page: Pdfjs.PDFPageViewport): void => { - this.props.pdf && this.props.loaded && this.props.loaded(page.width, page.height, this.props.pdf.numPages); + this.props.loaded(page.width, page.height, this.props.pdf.numPages); } @action getPlaceholderPage = (page: number) => { if (this._isPage[page] !== "none") { this._isPage[page] = "none"; this._visibleElements[page] = ( -
    +
    ); } } @@ -219,8 +197,8 @@ class Viewer extends React.Component { pdf={this.props.pdf} page={page} numPages={this.props.pdf!.numPages} - key={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${page + 1}` : "undefined"}`} - name={`${this.props.pdf ? this.props.pdf.fingerprint + `-page${page + 1}` : "undefined"}`} + key={`rendered-${page + 1}`} + name={`${this.props.pdf.fingerprint + `-page${page + 1}`}`} pageLoaded={this.pageLoaded} parent={this.props.parent} makePin={this.createPinAnnotation} @@ -243,38 +221,33 @@ class Viewer extends React.Component { this._isPage[page] = "image"; const address = this.props.url; let res = JSON.parse(await rp.get(DocServer.prepend(`/thumbnail${address.substring("files/".length, address.length - ".pdf".length)}-${page + 1}.PNG`))); - runInAction(() => this._visibleElements[page] = ); + runInAction(() => this._visibleElements[page] = + ); } } @computed get scrollY(): number { return this.props.scrollY; } + // startIndex: where to start rendering pages @computed get startIndex(): number { return Math.max(0, this.getPageFromScroll(this.scrollY) - this._pageBuffer); } + // endIndex: where to end rendering pages @computed get endIndex(): number { - let width = this._pageSizes.map(i => i ? i.width : 0); - return Math.min(this.props.pdf ? this.props.pdf.numPages - 1 : 0, this.getPageFromScroll(this.scrollY + Math.max(...width)) + this._pageBuffer); + let width = this._pageSizes.map(i => i.width); + return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + Math.max(...width)) + this._pageBuffer); } - /** - * @param startIndex: where to start rendering pages - * @param endIndex: where to end rendering pages - * @param forceRender: (optional), force pdfs to re-render, even if the page already exists - */ @action - renderPages = (startIndex: number, endIndex: number, forceRender: boolean = false) => { - if (this.props.pdf) { - // unrender pages outside of the pdf by replacing them with empty stand-in divs - for (let i = 0; i < this.props.pdf.numPages; i++) { - if (i < startIndex || i > endIndex) { - this.getPlaceholderPage(i); + renderPages = () => { + for (let i = 0; i < this.props.pdf.numPages; i++) { + if (i < this.startIndex || i > this.endIndex) { + this.getPlaceholderPage(i); // pages outside of the pdf use empty stand-in divs + } else { + if (this.props.parent.props.active()) { + this.getRenderedPage(i); } else { - if (this.props.parent.props.active()) { - this.getRenderedPage(i); - } else { - this.getPageImage(i); - } + this.getPageImage(i); } } } @@ -308,7 +281,6 @@ class Viewer extends React.Component { createPinAnnotation = (x: number, y: number, page: number): void => { let targetDoc = Docs.TextDocument({ width: 100, height: 50, title: "New Pin Annotation" }); - let pinAnno = new Doc(); pinAnno.x = x; pinAnno.y = y + this.getScrollFromPage(page); @@ -333,22 +305,16 @@ class Viewer extends React.Component { getPageFromScroll = (vOffset: number) => { let index = 0; let currOffset = vOffset; - 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++; + while (index < this._pageSizes.length && currOffset - this._pageSizes[index].height > 0) { + currOffset -= this._pageSizes[index++].height; } return index; } - getScrollFromPage = (index: number): number => { let counter = 0; - if (this.props.pdf && index < this.props.pdf.numPages) { - for (let i = 0; i < index; i++) { - if (this._pageSizes[i]) { - counter += this._pageSizes[i].height; - } - } + for (let i = 0; i < Math.min(this.props.pdf.numPages, index); i++) { + counter += this._pageSizes[i].height; } return counter; } @@ -392,7 +358,11 @@ class Viewer extends React.Component {
    {this._visibleElements}
    -
    +
    {this._annotations.map(anno => this.renderAnnotation(anno))}
    -- cgit v1.2.3-70-g09d2 From a3b8a57027d7c45ea19d259e1ec18fa6a8648c24 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 18 Jun 2019 08:49:02 -0400 Subject: looked like wrong code... --- src/client/views/pdf/PDFViewer.tsx | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'src/client') diff --git a/src/client/views/pdf/PDFViewer.tsx b/src/client/views/pdf/PDFViewer.tsx index 645afc636..e5fb32e53 100644 --- a/src/client/views/pdf/PDFViewer.tsx +++ b/src/client/views/pdf/PDFViewer.tsx @@ -234,8 +234,7 @@ class Viewer extends React.Component { // endIndex: where to end rendering pages @computed get endIndex(): number { - let width = this._pageSizes.map(i => i.width); - return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY + Math.max(...width)) + this._pageBuffer); + return Math.min(this.props.pdf.numPages - 1, this.getPageFromScroll(this.scrollY) + this._pageBuffer); } @action -- cgit v1.2.3-70-g09d2 From 4b8324fcf44c5d3c3a4b3f6e98a4d1dfce84811b Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 18 Jun 2019 08:53:01 -0400 Subject: removed trace --- src/client/views/nodes/PDFBox.tsx | 1 - 1 file changed, 1 deletion(-) (limited to 'src/client') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 3aaa5749d..e79182e9b 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -96,7 +96,6 @@ export class PDFBox extends DocComponent(PdfDocumen } render() { - trace(); // uses mozilla pdf as default const pdfUrl = Cast(this.props.Document.data, PdfField, new PdfField(window.origin + RouteStore.corsProxy + "/https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf")); console.log(pdfUrl); -- cgit v1.2.3-70-g09d2 From 64e6a941639aab8d7109178aa151a50909547309 Mon Sep 17 00:00:00 2001 From: Bob Zeleznik Date: Tue, 18 Jun 2019 09:05:41 -0400 Subject: fixed index out of range --- src/client/views/nodes/PDFBox.tsx | 1 - src/client/views/pdf/PDFViewer.tsx | 5 +++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'src/client') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index e79182e9b..38e91ac12 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -98,7 +98,6 @@ export class PDFBox extends DocComponent(PdfDocumen render() { // uses mozilla pdf as default const pdfUrl = Cast(this.props.Document.data, PdfField, new PdfField(window.origin + RouteStore.corsProxy + "/https://mozilla.github.io/pdf.js/web/compressed.tracemonkey-pldi-09.pdf")); - console.log(pdfUrl); let classname = "pdfBox-cont" + (this.props.isSelected() && !InkingControl.Instance.selectedTool && !this._alt ? "-interactive" : ""); return (
    { initialLoad = async () => { if (this._pageSizes.length === 0) { let pageSizes = Array<{ width: number, height: number }>(this.props.pdf.numPages); + this._isPage = Array(this.props.pdf.numPages); for (let i = 0; i < this.props.pdf.numPages; i++) { await this.props.pdf.getPage(i + 1).then(page => runInAction(() => pageSizes[i] = { width: page.view[2] * scale, height: page.view[3] * scale })); } - this.props.loaded(pageSizes[0].width, pageSizes[0].height, this.props.pdf.numPages); runInAction(() => - Array.from(Array((this._pageSizes = pageSizes).length).keys()).map(this.getPlaceholderPage)) + Array.from(Array((this._pageSizes = pageSizes).length).keys()).map(this.getPlaceholderPage)); + this.props.loaded(pageSizes[0].width, pageSizes[0].height, this.props.pdf.numPages); } } -- cgit v1.2.3-70-g09d2