From d808f36e6b874afd77bafd634e806b52203fa464 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Wed, 24 Apr 2019 21:11:40 -0400 Subject: PdfBox --- src/client/views/nodes/PDFBox.tsx | 56 ++++++++++++++++++++++----------------- 1 file changed, 31 insertions(+), 25 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 81ceb37f6..7fbfed1c0 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -6,10 +6,6 @@ import Measure from "react-measure"; //@ts-ignore import { Document, Page } from "react-pdf"; import 'react-pdf/dist/Page/AnnotationLayer.css'; -import { FieldWaiting, Opt } from '../../../fields/Field'; -import { ImageField } from '../../../fields/ImageField'; -import { KeyStore } from '../../../fields/KeyStore'; -import { PDFField } from '../../../fields/PDFField'; import { RouteStore } from "../../../server/RouteStore"; import { Utils } from '../../../Utils'; import { Annotation } from './Annotation'; @@ -19,6 +15,13 @@ import "./PDFBox.scss"; import { Sticky } from './Sticky'; //you should look at sticky and annotation, because they are used here import React = require("react"); import { SelectionManager } from "../../util/SelectionManager"; +import { Cast, FieldValue } from "../../../new_fields/Types"; +import { Opt } from "../../../new_fields/Doc"; +import { DocComponent } from "../DocComponent"; +import { makeInterface } from "../../../new_fields/Schema"; +import { positionSchema } from "./DocumentView"; +import { pageSchema } from "./ImageBox"; +import { ImageField, PdfField } from "../../../new_fields/URLField"; /** ALSO LOOK AT: Annotation.tsx, Sticky.tsx * This method renders PDF and puts all kinds of functionalities such as annotation, highlighting, @@ -51,8 +54,12 @@ import { SelectionManager } from "../../util/SelectionManager"; * * written by: Andrew Kim */ + +type PdfDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; +const PdfDocument = makeInterface(positionSchema, pageSchema); + @observer -export class PDFBox extends React.Component { +export class PDFBox extends DocComponent(PdfDocument) { public static LayoutString() { return FieldView.LayoutString(PDFBox); } private _mainDiv = React.createRef(); @@ -89,8 +96,8 @@ export class PDFBox extends React.Component { @observable private _interactive: boolean = false; @observable private _loaded: boolean = false; - @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, 1); } - @computed private get thumbnailPage() { return this.props.Document.GetNumber(KeyStore.ThumbnailPage, -1); } + @computed private get curPage() { return FieldValue(this.Document.curPage, 1); } + @computed private get thumbnailPage() { return Cast(this.props.Document.thumbnailPage, "number", -1); } componentDidMount() { this._reactionDisposer = reaction( @@ -380,14 +387,13 @@ export class PDFBox extends React.Component { saveThumbnail = () => { this._renderAsSvg = false; setTimeout(() => { - var me = this; - let nwidth = me.props.Document.GetNumber(KeyStore.NativeWidth, 0); - let nheight = me.props.Document.GetNumber(KeyStore.NativeHeight, 0); + let nwidth = FieldValue(this.Document.nativeWidth, 0); + let nheight = FieldValue(this.Document.nativeHeight, 0); htmlToImage.toPng(this._mainDiv.current!, { width: nwidth, height: nheight, quality: 1 }) .then(action((dataUrl: string) => { - me.props.Document.SetData(KeyStore.Thumbnail, new URL(dataUrl), ImageField); - me.props.Document.SetNumber(KeyStore.ThumbnailPage, me.props.Document.GetNumber(KeyStore.CurPage, -1)); - me._renderAsSvg = true; + this.props.Document.thumbnail = new ImageField(new URL(dataUrl)); + this.props.Document.thumbnailPage = FieldValue(this.Document.curPage, -1); + this._renderAsSvg = true; })) .catch(function (error: any) { console.error('oops, something went wrong!', error); @@ -414,7 +420,7 @@ export class PDFBox extends React.Component { } // bcz: the number of pages should really be set when the document is imported. - this.props.Document.SetNumber(KeyStore.NumPages, page._transport.numPages); + this.props.Document.numPages = page._transport.numPages; if (this._perPageInfo.length === 0) { //Makes sure it only runs once this._perPageInfo = [...Array(page._transport.numPages)]; } @@ -426,11 +432,11 @@ export class PDFBox extends React.Component { // bcz: the nativeHeight should really be set when the document is imported. // also, the native dimensions could be different for different pages of the PDF // so this design is flawed. - var nativeWidth = this.props.Document.GetNumber(KeyStore.NativeWidth, 0); - if (!this.props.Document.GetNumber(KeyStore.NativeHeight, 0)) { + var nativeWidth = FieldValue(this.Document.nativeWidth, 0); + if (!FieldValue(this.Document.nativeHeight, 0)) { var nativeHeight = nativeWidth * r.entry.height / r.entry.width; - this.props.Document.SetNumber(KeyStore.Height, nativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0)); - this.props.Document.SetNumber(KeyStore.NativeHeight, nativeHeight); + this.props.Document.height = nativeHeight / nativeWidth * FieldValue(this.Document.width, 0); + this.props.Document.nativeHeight = nativeHeight; } } @@ -438,8 +444,8 @@ export class PDFBox extends React.Component { get pdfContent() { let page = this.curPage; const renderHeight = 2400; - let pdfUrl = this.props.Document.GetT(this.props.fieldKey, PDFField); - let xf = this.props.Document.GetNumber(KeyStore.NativeHeight, 0) / renderHeight; + let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); + let xf = FieldValue(this.Document.nativeHeight, 0) / renderHeight; return
@@ -456,8 +462,8 @@ export class PDFBox extends React.Component { @computed get pdfRenderer() { let proxy = this._loaded ? (null) : this.imageProxyRenderer; - let pdfUrl = this.props.Document.GetT(this.props.fieldKey, PDFField); - if ((!this._interactive && proxy) || !pdfUrl || pdfUrl === FieldWaiting) { + let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); + if ((!this._interactive && proxy) || !pdfUrl) { return proxy; } return [ @@ -470,10 +476,10 @@ export class PDFBox extends React.Component { @computed get imageProxyRenderer() { - let thumbField = this.props.Document.Get(KeyStore.Thumbnail); + let thumbField = this.props.Document.thumbnail; if (thumbField) { - let path = thumbField === FieldWaiting || this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" : - thumbField instanceof ImageField ? thumbField.Data.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; + let path = this.thumbnailPage !== this.curPage ? "https://image.flaticon.com/icons/svg/66/66163.svg" : + thumbField instanceof ImageField ? thumbField.url.href : "http://cs.brown.edu/people/bcz/prairie.jpg"; return ; } return (null); -- cgit v1.2.3-70-g09d2 From a2751d16babb38cde2b86b1cb8fc5d74c15762d7 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 28 Apr 2019 00:23:18 -0400 Subject: Decent amount of stuff is working --- src/client/views/Main.tsx | 2 +- src/client/views/collections/CollectionBaseView.tsx | 2 +- src/client/views/collections/CollectionPDFView.tsx | 3 ++- src/client/views/collections/CollectionVideoView.tsx | 3 ++- src/client/views/collections/CollectionView.tsx | 3 ++- .../views/collections/collectionFreeForm/CollectionFreeFormView.tsx | 2 +- src/client/views/nodes/CollectionFreeFormDocumentView.tsx | 1 + src/client/views/nodes/DocumentView.tsx | 4 ++-- src/client/views/nodes/FormattedTextBox.tsx | 3 ++- src/client/views/nodes/PDFBox.tsx | 2 +- src/new_fields/RichTextField.ts | 2 ++ src/new_fields/Types.ts | 2 +- 12 files changed, 18 insertions(+), 11 deletions(-) (limited to 'src/client/views/nodes/PDFBox.tsx') diff --git a/src/client/views/Main.tsx b/src/client/views/Main.tsx index 4a68d1c68..98c5a5306 100644 --- a/src/client/views/Main.tsx +++ b/src/client/views/Main.tsx @@ -165,7 +165,7 @@ export class Main extends React.Component { @action openWorkspace = async (doc: Doc, fromHistory = false) => { this.mainContainer = doc; - fromHistory || window.history.pushState(null, StrCast(doc.title), "/doc/" + doc.Id); + fromHistory || window.history.pushState(null, StrCast(doc.title), "/doc/" + doc[Id]); const col = await Cast(CurrentUserUtils.UserDocument.optionalRightCollection, Doc); // if there is a pending doc, and it has new data, show it (syip: we use a timeout to prevent collection docking view from being uninitialized) setTimeout(async () => { diff --git a/src/client/views/collections/CollectionBaseView.tsx b/src/client/views/collections/CollectionBaseView.tsx index b2fba1415..ed761d3f3 100644 --- a/src/client/views/collections/CollectionBaseView.tsx +++ b/src/client/views/collections/CollectionBaseView.tsx @@ -95,7 +95,7 @@ export class CollectionBaseView extends React.Component { //TODO This won't create the field if it doesn't already exist const value = Cast(props.Document[props.fieldKey], listSpec(Doc)); if (value !== undefined) { - if (allowDuplicates || !value.some(v => v.Id === doc.Id)) { + if (allowDuplicates || !value.some(v => v[Id] === doc[Id])) { value.push(doc); } } else { diff --git a/src/client/views/collections/CollectionPDFView.tsx b/src/client/views/collections/CollectionPDFView.tsx index 99438b4e8..5a1af354a 100644 --- a/src/client/views/collections/CollectionPDFView.tsx +++ b/src/client/views/collections/CollectionPDFView.tsx @@ -8,6 +8,7 @@ import { FieldView, FieldViewProps } from "../nodes/FieldView"; import { CollectionRenderProps, CollectionBaseView, CollectionViewType } from "./CollectionBaseView"; import { emptyFunction } from "../../../Utils"; import { NumCast } from "../../../new_fields/Types"; +import { Id } from "../../../new_fields/RefField"; @observer @@ -33,7 +34,7 @@ export class CollectionPDFView extends React.Component { } onContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "PDFOptions", event: emptyFunction }); } } diff --git a/src/client/views/collections/CollectionVideoView.tsx b/src/client/views/collections/CollectionVideoView.tsx index d45be228a..7232ecea2 100644 --- a/src/client/views/collections/CollectionVideoView.tsx +++ b/src/client/views/collections/CollectionVideoView.tsx @@ -8,6 +8,7 @@ import { CollectionFreeFormView } from "./collectionFreeForm/CollectionFreeFormV import { FieldView, FieldViewProps } from "../nodes/FieldView"; import { emptyFunction } from "../../../Utils"; import { NumCast } from "../../../new_fields/Types"; +import { Id } from "../../../new_fields/RefField"; @observer @@ -107,7 +108,7 @@ export class CollectionVideoView extends React.Component { } onContextMenu = (e: React.MouseEvent): void => { - if (!e.isPropagationStopped() && this.props.Document.Id !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!e.isPropagationStopped() && this.props.Document[Id] !== "mainDoc") { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "VideoOptions", event: emptyFunction }); } } diff --git a/src/client/views/collections/CollectionView.tsx b/src/client/views/collections/CollectionView.tsx index b72065bca..c2049a09a 100644 --- a/src/client/views/collections/CollectionView.tsx +++ b/src/client/views/collections/CollectionView.tsx @@ -10,6 +10,7 @@ import { CurrentUserUtils } from '../../../server/authentication/models/current_ import { observer } from 'mobx-react'; import { undoBatch } from '../../util/UndoManager'; import { trace } from 'mobx'; +import { Id } from '../../../new_fields/RefField'; @observer export class CollectionView extends React.Component { @@ -31,7 +32,7 @@ export class CollectionView extends React.Component { get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey === "annotations"; } // bcz: ? Why do we need to compare Id's? onContextMenu = (e: React.MouseEvent): void => { - if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document.Id !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 + if (!this.isAnnotationOverlay && !e.isPropagationStopped() && this.props.Document[Id] !== CurrentUserUtils.MainDocId) { // need to test this because GoldenLayout causes a parallel hierarchy in the React DOM for its children and the main document view7 ContextMenu.Instance.addItem({ description: "Freeform", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Freeform) }); ContextMenu.Instance.addItem({ description: "Schema", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Schema) }); ContextMenu.Instance.addItem({ description: "Treeview", event: undoBatch(() => this.props.Document.viewType = CollectionViewType.Tree) }); diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index dfacca204..dcded7648 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -257,7 +257,7 @@ export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { moveDocument: this.props.moveDocument, ScreenToLocalTransform: this.getTransform, isTopMost: false, - selectOnLoad: document.Id === this._selectOnLoaded, + selectOnLoad: document[Id] === this._selectOnLoaded, PanelWidth: () => Cast(document.width, "number", 0),//TODO Types These are inline functions PanelHeight: () => Cast(document.height, "number", 0), ContentScaling: returnOne, diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 376af0b36..8766eb7ea 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -20,6 +20,7 @@ const schema = createSchema({ zIndex: "number" }); +//TODO Types: The import order is wrong, so positionSchema is undefined type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>; const FreeformDocument = makeInterface(schema, positionSchema); diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index c304b6a35..3814eeb9c 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -139,7 +139,7 @@ export class DocumentView extends DocComponent(Docu } onClick = (e: React.MouseEvent): void => { - if (CurrentUserUtils.MainDocId !== this.props.Document.Id && + if (CurrentUserUtils.MainDocId !== this.props.Document[Id] && (Math.abs(e.clientX - this._downX) < Utils.DRAG_THRESHOLD && Math.abs(e.clientY - this._downY) < Utils.DRAG_THRESHOLD)) { SelectionManager.SelectDoc(this, e.ctrlKey); @@ -247,7 +247,7 @@ export class DocumentView extends DocComponent(Docu ContextMenu.Instance.addItem({ description: "Fields", event: this.fieldsClicked }); ContextMenu.Instance.addItem({ description: "Center", event: () => this.props.focus(this.props.Document) }); ContextMenu.Instance.addItem({ description: "Open Right", event: () => CollectionDockingView.Instance.AddRightSplit(this.props.Document) }); - ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document.Id)) }); + ContextMenu.Instance.addItem({ description: "Copy URL", event: () => Utils.CopyText(DocServer.prepend("/doc/" + this.props.Document[Id])) }); ContextMenu.Instance.addItem({ description: "Copy ID", event: () => Utils.CopyText(this.props.Document[Id]) }); //ContextMenu.Instance.addItem({ description: "Docking", event: () => this.props.Document.SetNumber(KeyStore.ViewType, CollectionViewType.Docking) }) ContextMenu.Instance.addItem({ description: "Delete", event: this.deleteClicked }); diff --git a/src/client/views/nodes/FormattedTextBox.tsx b/src/client/views/nodes/FormattedTextBox.tsx index 96512718f..c4c720ca9 100644 --- a/src/client/views/nodes/FormattedTextBox.tsx +++ b/src/client/views/nodes/FormattedTextBox.tsx @@ -22,6 +22,7 @@ import { observer } from "mobx-react"; import { InkingControl } from "../InkingControl"; import { StrCast, Cast } from "../../../new_fields/Types"; import { RichTextField } from "../../../new_fields/RichTextField"; +import { Id } from "../../../new_fields/RefField"; const { buildMenuItems } = require("prosemirror-example-setup"); const { menuBar } = require("prosemirror-menu"); @@ -108,7 +109,7 @@ export class FormattedTextBox extends DocComponent<(FieldViewProps & FormattedTe }; if (this.props.isOverlay) { - this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc.Id, + this._inputReactionDisposer = reaction(() => MainOverlayTextBox.Instance.TextDoc && MainOverlayTextBox.Instance.TextDoc[Id], () => { if (this._editorView) { this._editorView.destroy(); diff --git a/src/client/views/nodes/PDFBox.tsx b/src/client/views/nodes/PDFBox.tsx index 7fbfed1c0..9f0849492 100644 --- a/src/client/views/nodes/PDFBox.tsx +++ b/src/client/views/nodes/PDFBox.tsx @@ -447,7 +447,7 @@ export class PDFBox extends DocComponent(PdfDocumen let pdfUrl = Cast(this.props.Document[this.props.fieldKey], PdfField); let xf = FieldValue(this.Document.nativeHeight, 0) / renderHeight; return
- + {({ measureRef }) =>
diff --git a/src/new_fields/RichTextField.ts b/src/new_fields/RichTextField.ts index 0fa3cf73c..f2033d5a7 100644 --- a/src/new_fields/RichTextField.ts +++ b/src/new_fields/RichTextField.ts @@ -1,6 +1,8 @@ import { ObjectField } from "./ObjectField"; import { serializable } from "serializr"; +import { Deserializable } from "../client/util/SerializationHelper"; +@Deserializable("RichTextField") export class RichTextField extends ObjectField { @serializable(true) readonly Data: string; diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 3f8eabd45..e179c2602 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -76,7 +76,7 @@ type WithoutList = T extends List ? R[] : T; export function FieldValue>(field: FieldResult, defaultValue: U): WithoutList; export function FieldValue(field: FieldResult): Opt; export function FieldValue(field: FieldResult, defaultValue?: T): Opt { - return field instanceof Promise ? defaultValue : field; + return (field instanceof Promise || field === undefined) ? defaultValue : field; } export interface PromiseLike { -- cgit v1.2.3-70-g09d2