From 1eb965a5d9c8aaebf1970bc645edecfb7017b601 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sat, 20 Apr 2019 03:29:35 -0400 Subject: Made the switch in a couple more classes --- src/client/views/nodes/FieldView.tsx | 45 +++++++++++++++--------------------- 1 file changed, 18 insertions(+), 27 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 93e385821..d8de5afec 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -1,30 +1,21 @@ import React = require("react"); import { observer } from "mobx-react"; import { computed } from "mobx"; -import { Field, FieldWaiting, FieldValue, Opt } from "../../../fields/Field"; -import { Document } from "../../../fields/Document"; -import { TextField } from "../../../fields/TextField"; -import { NumberField } from "../../../fields/NumberField"; -import { RichTextField } from "../../../fields/RichTextField"; -import { ImageField } from "../../../fields/ImageField"; -import { VideoField } from "../../../fields/VideoField"; -import { Key } from "../../../fields/Key"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; import { WebBox } from "./WebBox"; import { VideoBox } from "./VideoBox"; import { AudioBox } from "./AudioBox"; -import { AudioField } from "../../../fields/AudioField"; -import { ListField } from "../../../fields/ListField"; import { DocumentContentsView } from "./DocumentContentsView"; import { Transform } from "../../util/Transform"; -import { KeyStore } from "../../../fields/KeyStore"; -import { returnFalse, emptyDocFunction, emptyFunction, returnOne } from "../../../Utils"; +import { returnFalse, emptyFunction, returnOne } from "../../../Utils"; import { CollectionView } from "../collections/CollectionView"; import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; import { IconField } from "../../../fields/IconFIeld"; import { IconBox } from "./IconBox"; +import { Opt, Doc, Field, FieldValue, FieldWaiting } from "../../../new_fields/Doc"; +import { List } from "../../../new_fields/List"; // @@ -33,9 +24,9 @@ import { IconBox } from "./IconBox"; // See the LayoutString method on each field view : ImageBox, FormattedTextBox, etc. // export interface FieldViewProps { - fieldKey: Key; + fieldKey: string; ContainingCollectionView: Opt; - Document: Document; + Document: Doc; isSelected: () => boolean; select: (isCtrlPressed: boolean) => void; isTopMost: boolean; @@ -56,17 +47,17 @@ export class FieldView extends React.Component { } @computed - get field(): FieldValue { - const { Document: doc, fieldKey } = this.props; - return doc.Get(fieldKey); + get field(): FieldValue { + const { Document, fieldKey } = this.props; + return Document[fieldKey]; } render() { const field = this.field; if (!field) { return

{''}

; } - if (field instanceof TextField) { - return

{field.Data}

; + if (typeof field === "string") { + return

{field}

; } else if (field instanceof RichTextField) { return ; @@ -83,7 +74,7 @@ export class FieldView extends React.Component { else if (field instanceof AudioField) { return ; } - else if (field instanceof Document) { + else if (field instanceof Doc) { return ( { PanelHeight={() => 100} isTopMost={true} //TODO Why is this top most? selectOnLoad={false} - focus={emptyDocFunction} + focus={emptyFunction} isSelected={returnFalse} select={returnFalse} - layoutKey={KeyStore.Layout} + layoutKey={"layout"} ContainingCollectionView={this.props.ContainingCollectionView} parentActive={this.props.active} whenActiveChanged={this.props.whenActiveChanged} /> ); } - else if (field instanceof ListField) { + else if (field instanceof List) { return (
- {(field as ListField).Data.map(f => f instanceof Document ? f.Title : f.GetValue().toString()).join(", ")} + {field.map(f => f instanceof Doc ? f.title : f.toString()).join(", ")}
); } // bcz: this belongs here, but it doesn't render well so taking it out for now // else if (field instanceof HtmlField) { // return // } - else if (field instanceof NumberField) { - return

{field.Data}

; + else if (typeof field === "number") { + return

{field}

; } else if (field !== FieldWaiting) { - return

{JSON.stringify(field.GetValue())}

; + return

{JSON.stringify(field)}

; } else { return

{"Waiting for server..."}

; -- cgit v1.2.3-70-g09d2 From ab8b4ffd7f3b89600a71d3167490c40a59be433e Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 21 Apr 2019 01:46:02 -0400 Subject: More changes/fixes --- src/client/views/collections/CollectionSubView.tsx | 354 +++++++++++---------- .../collectionFreeForm/CollectionFreeFormView.tsx | 21 +- src/client/views/nodes/FieldView.tsx | 8 +- src/new_fields/Schema.ts | 15 +- src/new_fields/Types.ts | 2 +- 5 files changed, 210 insertions(+), 190 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/views/collections/CollectionSubView.tsx b/src/client/views/collections/CollectionSubView.tsx index 5c3b2e586..3add288fd 100644 --- a/src/client/views/collections/CollectionSubView.tsx +++ b/src/client/views/collections/CollectionSubView.tsx @@ -18,11 +18,13 @@ import * as rp from 'request-promise'; import { CollectionView } from "./CollectionView"; import { CollectionPDFView } from "./CollectionPDFView"; import { CollectionVideoView } from "./CollectionVideoView"; +import { Doc } from "../../../new_fields/Doc"; +import { DocComponent } from "../DocComponent"; export interface CollectionViewProps extends FieldViewProps { - addDocument: (document: Document, allowDuplicates?: boolean) => boolean; - removeDocument: (document: Document) => boolean; - moveDocument: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean; + addDocument: (document: Doc, allowDuplicates?: boolean) => boolean; + removeDocument: (document: Doc) => boolean; + moveDocument: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; PanelWidth: () => number; PanelHeight: () => number; } @@ -33,198 +35,202 @@ export interface SubCollectionViewProps extends CollectionViewProps { export type CursorEntry = TupleField<[string, string], [number, number]>; -export class CollectionSubView extends React.Component { - private dropDisposer?: DragManager.DragDropDisposer; - protected createDropTarget = (ele: HTMLDivElement) => { - if (this.dropDisposer) { - this.dropDisposer(); +export function CollectionSubView(schemaCtor: (doc: Doc) => T) { + class CollectionSubView extends DocComponent(schemaCtor) { + private dropDisposer?: DragManager.DragDropDisposer; + protected createDropTarget = (ele: HTMLDivElement) => { + if (this.dropDisposer) { + this.dropDisposer(); + } + if (ele) { + this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + } } - if (ele) { - this.dropDisposer = DragManager.MakeDropTarget(ele, { handlers: { drop: this.drop.bind(this) } }); + protected CreateDropTarget(ele: HTMLDivElement) { + this.createDropTarget(ele); } - } - protected CreateDropTarget(ele: HTMLDivElement) { - this.createDropTarget(ele); - } - @action - protected setCursorPosition(position: [number, number]) { - let ind; - let doc = this.props.Document; - let id = CurrentUserUtils.id; - let email = CurrentUserUtils.email; - if (id && email) { - let textInfo: [string, string] = [id, email]; - doc.GetTAsync(KeyStore.Prototype, Document).then(proto => { - if (!proto) { - return; - } - proto.GetOrCreateAsync>(KeyStore.Cursors, ListField, action((field: ListField) => { - let cursors = field.Data; - if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) { - cursors[ind].Data[1] = position; - } else { - let entry = new TupleField<[string, string], [number, number]>([textInfo, position]); - cursors.push(entry); + @action + protected setCursorPosition(position: [number, number]) { + let ind; + let doc = this.props.Document; + let id = CurrentUserUtils.id; + let email = CurrentUserUtils.email; + if (id && email) { + let textInfo: [string, string] = [id, email]; + doc.GetTAsync(KeyStore.Prototype, Document).then(proto => { + if (!proto) { + return; } - })); - }); + proto.GetOrCreateAsync>(KeyStore.Cursors, ListField, action((field: ListField) => { + let cursors = field.Data; + if (cursors.length > 0 && (ind = cursors.findIndex(entry => entry.Data[0][0] === id)) > -1) { + cursors[ind].Data[1] = position; + } else { + let entry = new TupleField<[string, string], [number, number]>([textInfo, position]); + cursors.push(entry); + } + })); + }); + } } - } - @undoBatch - @action - protected drop(e: Event, de: DragManager.DropEvent): boolean { - if (de.data instanceof DragManager.DocumentDragData) { - if (de.data.aliasOnDrop || de.data.copyOnDrop) { - [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => - de.data.draggedDocuments.map((draggedDocument: Document, i: number) => - draggedDocument.GetTAsync(key, NumberField, (f: Opt) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null))); - } - let added = false; - if (de.data.aliasOnDrop || de.data.copyOnDrop) { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); - } else if (de.data.moveDocument) { - const move = de.data.moveDocument; - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = move(d, this.props.Document, this.props.addDocument); - return moved || added; - }, false); - } else { - added = de.data.droppedDocuments.reduce((added: boolean, d) => { - let moved = this.props.addDocument(d); - return moved || added; - }, false); + @undoBatch + @action + protected drop(e: Event, de: DragManager.DropEvent): boolean { + if (de.data instanceof DragManager.DocumentDragData) { + if (de.data.aliasOnDrop || de.data.copyOnDrop) { + [KeyStore.Width, KeyStore.Height, KeyStore.CurPage].map(key => + de.data.draggedDocuments.map((draggedDocument: Document, i: number) => + draggedDocument.GetTAsync(key, NumberField, (f: Opt) => f ? de.data.droppedDocuments[i].SetNumber(key, f.Data) : null))); + } + let added = false; + if (de.data.aliasOnDrop || de.data.copyOnDrop) { + added = de.data.droppedDocuments.reduce((added: boolean, d) => { + let moved = this.props.addDocument(d); + return moved || added; + }, false); + } else if (de.data.moveDocument) { + const move = de.data.moveDocument; + added = de.data.droppedDocuments.reduce((added: boolean, d) => { + let moved = move(d, this.props.Document, this.props.addDocument); + return moved || added; + }, false); + } else { + added = de.data.droppedDocuments.reduce((added: boolean, d) => { + let moved = this.props.addDocument(d); + return moved || added; + }, false); + } + e.stopPropagation(); + return added; } - e.stopPropagation(); - return added; + return false; } - return false; - } - protected async getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise> { - let ctor: ((path: string, options: DocumentOptions) => (Document | Promise)) | undefined = undefined; - if (type.indexOf("image") !== -1) { - ctor = Documents.ImageDocument; - } - if (type.indexOf("video") !== -1) { - ctor = Documents.VideoDocument; - } - if (type.indexOf("audio") !== -1) { - ctor = Documents.AudioDocument; - } - if (type.indexOf("pdf") !== -1) { - ctor = Documents.PdfDocument; - options.nativeWidth = 1200; - } - if (type.indexOf("excel") !== -1) { - ctor = Documents.DBDocument; - options.copyDraggedItems = true; - } - if (type.indexOf("html") !== -1) { - if (path.includes('localhost')) { - let s = path.split('/'); - let id = s[s.length - 1]; - Server.GetField(id).then(field => { - if (field instanceof Document) { - let alias = field.CreateAlias(); - alias.SetNumber(KeyStore.X, options.x || 0); - alias.SetNumber(KeyStore.Y, options.y || 0); - alias.SetNumber(KeyStore.Width, options.width || 300); - alias.SetNumber(KeyStore.Height, options.height || options.width || 300); - this.props.addDocument(alias, false); - } - }); - return undefined; + protected async getDocumentFromType(type: string, path: string, options: DocumentOptions): Promise> { + let ctor: ((path: string, options: DocumentOptions) => (Document | Promise)) | undefined = undefined; + if (type.indexOf("image") !== -1) { + ctor = Documents.ImageDocument; + } + if (type.indexOf("video") !== -1) { + ctor = Documents.VideoDocument; + } + if (type.indexOf("audio") !== -1) { + ctor = Documents.AudioDocument; + } + if (type.indexOf("pdf") !== -1) { + ctor = Documents.PdfDocument; + options.nativeWidth = 1200; + } + if (type.indexOf("excel") !== -1) { + ctor = Documents.DBDocument; + options.copyDraggedItems = true; } - ctor = Documents.WebDocument; - options = { height: options.width, ...options, title: path }; + if (type.indexOf("html") !== -1) { + if (path.includes('localhost')) { + let s = path.split('/'); + let id = s[s.length - 1]; + Server.GetField(id).then(field => { + if (field instanceof Document) { + let alias = field.CreateAlias(); + alias.SetNumber(KeyStore.X, options.x || 0); + alias.SetNumber(KeyStore.Y, options.y || 0); + alias.SetNumber(KeyStore.Width, options.width || 300); + alias.SetNumber(KeyStore.Height, options.height || options.width || 300); + this.props.addDocument(alias, false); + } + }); + return undefined; + } + ctor = Documents.WebDocument; + options = { height: options.width, ...options, title: path }; + } + return ctor ? ctor(path, options) : undefined; } - return ctor ? ctor(path, options) : undefined; - } - @undoBatch - @action - protected onDrop(e: React.DragEvent, options: DocumentOptions): void { - let html = e.dataTransfer.getData("text/html"); - let text = e.dataTransfer.getData("text/plain"); + @undoBatch + @action + protected onDrop(e: React.DragEvent, options: DocumentOptions): void { + let html = e.dataTransfer.getData("text/html"); + let text = e.dataTransfer.getData("text/plain"); - if (text && text.startsWith("[] = []; - // tslint:disable-next-line:prefer-for-of - for (let i = 0; i < e.dataTransfer.items.length; i++) { - const upload = window.location.origin + RouteStore.upload; - let item = e.dataTransfer.items[i]; - if (item.kind === "string" && item.type.indexOf("uri") !== -1) { - let str: string; - let prom = new Promise(resolve => e.dataTransfer.items[i].getAsString(resolve)) - .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s))))) - .then(result => { - let type = result.headers["content-type"]; - if (type) { - this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }) - .then(doc => doc && this.props.addDocument(doc, false)); - } - }); - promises.push(prom); + if (html && html.indexOf("[] = []; + // tslint:disable-next-line:prefer-for-of + for (let i = 0; i < e.dataTransfer.items.length; i++) { + const upload = window.location.origin + RouteStore.upload; + let item = e.dataTransfer.items[i]; + if (item.kind === "string" && item.type.indexOf("uri") !== -1) { + let str: string; + let prom = new Promise(resolve => e.dataTransfer.items[i].getAsString(resolve)) + .then(action((s: string) => rp.head(ServerUtils.prepend(RouteStore.corsProxy + "/" + (str = s))))) + .then(result => { + let type = result.headers["content-type"]; + if (type) { + this.getDocumentFromType(type, str, { ...options, width: 300, nativeWidth: 300 }) + .then(doc => doc && this.props.addDocument(doc, false)); + } + }); + promises.push(prom); } - let dropFileName = file ? file.name : "-empty-"; - - let prom = fetch(upload, { - method: 'POST', - body: formData - }).then(async (res: Response) => { - (await res.json()).map(action((file: any) => { - let path = window.location.origin + file; - let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName }); - - docPromise.then(action((doc?: Document) => { - let docs = this.props.Document.GetT(KeyStore.Data, ListField); - if (docs !== FieldWaiting) { - if (!docs) { - docs = new ListField(); - this.props.Document.Set(KeyStore.Data, docs); - } - if (doc) { - docs.Data.push(doc); + let type = item.type; + if (item.kind === "file") { + let file = item.getAsFile(); + let formData = new FormData(); + + if (file) { + formData.append('file', file); + } + let dropFileName = file ? file.name : "-empty-"; + + let prom = fetch(upload, { + method: 'POST', + body: formData + }).then(async (res: Response) => { + (await res.json()).map(action((file: any) => { + let path = window.location.origin + file; + let docPromise = this.getDocumentFromType(type, path, { ...options, nativeWidth: 600, width: 300, title: dropFileName }); + + docPromise.then(action((doc?: Document) => { + let docs = this.props.Document.GetT(KeyStore.Data, ListField); + if (docs !== FieldWaiting) { + if (!docs) { + docs = new ListField(); + this.props.Document.Set(KeyStore.Data, docs); + } + if (doc) { + docs.Data.push(doc); + } } - } + })); })); - })); - }); - promises.push(prom); + }); + promises.push(prom); + } } - } - if (promises.length) { - Promise.all(promises).finally(() => batch.end()); - } else { - batch.end(); + if (promises.length) { + Promise.all(promises).finally(() => batch.end()); + } else { + batch.end(); + } } } + return CollectionSubView; } + diff --git a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx index 945c01059..32104b49d 100644 --- a/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx +++ b/src/client/views/collections/collectionFreeForm/CollectionFreeFormView.tsx @@ -1,7 +1,5 @@ import { action, computed, observable, trace } from "mobx"; import { observer } from "mobx-react"; -import { Document } from "../../../../fields/Document"; -import { KeyStore } from "../../../../fields/KeyStore"; import { emptyFunction, returnFalse, returnOne } from "../../../../Utils"; import { DocumentManager } from "../../../util/DocumentManager"; import { DragManager } from "../../../util/DragManager"; @@ -13,7 +11,7 @@ import { InkingCanvas } from "../../InkingCanvas"; import { MainOverlayTextBox } from "../../MainOverlayTextBox"; import { CollectionFreeFormDocumentView } from "../../nodes/CollectionFreeFormDocumentView"; import { DocumentContentsView } from "../../nodes/DocumentContentsView"; -import { DocumentViewProps } from "../../nodes/DocumentView"; +import { DocumentViewProps, positionSchema } from "../../nodes/DocumentView"; import { CollectionSubView } from "../CollectionSubView"; import { CollectionFreeFormLinksView } from "./CollectionFreeFormLinksView"; import { CollectionFreeFormRemoteCursors } from "./CollectionFreeFormRemoteCursors"; @@ -21,17 +19,28 @@ import "./CollectionFreeFormView.scss"; import { MarqueeView } from "./MarqueeView"; import React = require("react"); import v5 = require("uuid/v5"); -import { BooleanField } from "../../../../fields/BooleanField"; +import { createSchema, makeInterface } from "../../../../new_fields/Schema"; +import { Doc } from "../../../../new_fields/Doc"; +import { FieldValue } from "../../../../new_fields/Types"; + +export const panZoomSchema = createSchema({ + panX: "number", + panY: "number", + zoom: "number" +}); + +type PanZoomDocument = makeInterface<[typeof panZoomSchema, typeof positionSchema]>; +const PanZoomDocument: (doc: Doc) => PanZoomDocument = makeInterface(panZoomSchema, positionSchema); @observer -export class CollectionFreeFormView extends CollectionSubView { +export class CollectionFreeFormView extends CollectionSubView(PanZoomDocument) { private _selectOnLoaded: string = ""; // id of document that should be selected once it's loaded (used for click-to-type) private _lastX: number = 0; private _lastY: number = 0; private get _pwidth() { return this.props.PanelWidth(); } private get _pheight() { return this.props.PanelHeight(); } - @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } + @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth, 0); } @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } private get borderWidth() { return this.isAnnotationOverlay ? 0 : COLLECTION_BORDER_WIDTH; } private get isAnnotationOverlay() { return this.props.fieldKey && this.props.fieldKey.Id === KeyStore.Annotations.Id; } // bcz: ? Why do we need to compare Id's? diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index d8de5afec..845213366 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -31,13 +31,13 @@ export interface FieldViewProps { select: (isCtrlPressed: boolean) => void; isTopMost: boolean; selectOnLoad: boolean; - addDocument?: (document: Document, allowDuplicates?: boolean) => boolean; - removeDocument?: (document: Document) => boolean; - moveDocument?: (document: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean; + addDocument?: (document: Doc, allowDuplicates?: boolean) => boolean; + removeDocument?: (document: Doc) => boolean; + moveDocument?: (document: Doc, targetCollection: Doc, addDocument: (document: Doc) => boolean) => boolean; ScreenToLocalTransform: () => Transform; active: () => boolean; whenActiveChanged: (isActive: boolean) => void; - focus: (doc: Document) => void; + focus: (doc: Doc) => void; } @observer diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index 1d1f56844..6022716be 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -1,9 +1,10 @@ import { Interface, ToInterface, Cast, FieldCtor, ToConstructor, HasTail, Head, Tail } from "./Types"; -import { Doc } from "./Doc"; +import { Doc, Field, ObjectField } from "./Doc"; +import { URLField } from "./URLField"; -type All = { - 1: makeInterface, U> & All, U>, - 0: makeInterface, U> +type All = { + 1: makeInterface<[Head], U> & All, U>, + 0: makeInterface<[Head], U> }[HasTail extends true ? 1 : 0]; type AllToInterface = { @@ -11,10 +12,14 @@ type AllToInterface = { 0: ToInterface> }[HasTail extends true ? 1 : 0]; +export const emptySchema = createSchema({}); +export const Document = makeInterface(emptySchema); +export type Document = makeInterface<[typeof emptySchema]>; + export type makeInterface = Partial> & U; // export function makeInterface(schemas: T): (doc: U) => All; // export function makeInterface(schema: T): (doc: U) => makeInterface; -export function makeInterface(schemas: T): (doc: U) => All { +export function makeInterface(...schemas: T): (doc: U) => makeInterface { let schema: Interface = {}; for (const s of schemas) { for (const key in s) { diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 0392dc2fb..e4d15e276 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -11,7 +11,7 @@ export type ToType = export type ToConstructor = T extends string ? "string" : T extends number ? "number" : - T extends boolean ? "boolean" : { new(...args: any[]): T }; + T extends boolean ? "boolean" : new (...args: any[]) => T; export type ToInterface = { [P in keyof T]: ToType; -- cgit v1.2.3-70-g09d2 From 393d351420b3a0d28f4cd1ea8b674fa5d04bfcde Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Sun, 21 Apr 2019 23:40:48 -0400 Subject: More fixes --- .../views/collections/CollectionDockingView.tsx | 6 ++-- .../views/nodes/CollectionFreeFormDocumentView.tsx | 2 +- src/client/views/nodes/DocumentView.tsx | 2 +- src/client/views/nodes/FieldView.tsx | 8 ++--- src/client/views/nodes/ImageBox.tsx | 15 +++++----- src/client/views/nodes/VideoBox.tsx | 35 ++++++++++++---------- src/client/views/nodes/WebBox.tsx | 4 +-- src/debug/Test.tsx | 12 ++++---- src/new_fields/Doc.ts | 4 +-- src/new_fields/Schema.ts | 22 +++----------- src/new_fields/Types.ts | 11 +++---- src/new_fields/URLField.ts | 9 ++++-- 12 files changed, 62 insertions(+), 68 deletions(-) (limited to 'src/client/views/nodes/FieldView.tsx') diff --git a/src/client/views/collections/CollectionDockingView.tsx b/src/client/views/collections/CollectionDockingView.tsx index 7b204cbdc..86ee7cea9 100644 --- a/src/client/views/collections/CollectionDockingView.tsx +++ b/src/client/views/collections/CollectionDockingView.tsx @@ -16,7 +16,7 @@ import { ServerUtils } from "../../../server/ServerUtil"; import { DragManager, DragLinksAsDocuments } from "../../util/DragManager"; import { Transform } from '../../util/Transform'; import { Doc, Id, Opt, Field, FieldId } from "../../../new_fields/Doc"; -import { Cast, FieldValue } from "../../../new_fields/Types"; +import { Cast } from "../../../new_fields/Types"; import { List } from "../../../new_fields/List"; import { DocServer } from "../../DocServer"; @@ -336,8 +336,8 @@ export class DockedFrameRenderer extends React.Component { ScreenToLocalTransform = () => { if (this._mainCont.current && this._mainCont.current.children) { - let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current!.children[0].firstChild as HTMLElement); - scale = Utils.GetScreenTransform(this._mainCont.current!).scale; + let { scale, translateX, translateY } = Utils.GetScreenTransform(this._mainCont.current.children[0].firstChild as HTMLElement); + scale = Utils.GetScreenTransform(this._mainCont.current).scale; return CollectionDockingView.Instance.props.ScreenToLocalTransform().translate(-translateX, -translateY).scale(scale / this.contentScaling()); } return Transform.Identity(); diff --git a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx index 27fd25b5c..c6eea5623 100644 --- a/src/client/views/nodes/CollectionFreeFormDocumentView.tsx +++ b/src/client/views/nodes/CollectionFreeFormDocumentView.tsx @@ -18,7 +18,7 @@ const schema = createSchema({ }); type FreeformDocument = makeInterface<[typeof schema, typeof positionSchema]>; -const FreeformDocument = makeInterface([schema, positionSchema]); +const FreeformDocument = makeInterface(schema, positionSchema); @observer export class CollectionFreeFormDocumentView extends DocComponent(FreeformDocument) { diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index f1a12e6db..c0afc192e 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -56,7 +56,7 @@ export const positionSchema = createSchema({ }); type Document = makeInterface<[typeof schema]>; -const Document = makeInterface([schema]); +const Document = makeInterface(schema); @observer export class DocumentView extends DocComponent(Document) { diff --git a/src/client/views/nodes/FieldView.tsx b/src/client/views/nodes/FieldView.tsx index 845213366..b11a87d75 100644 --- a/src/client/views/nodes/FieldView.tsx +++ b/src/client/views/nodes/FieldView.tsx @@ -3,19 +3,19 @@ import { observer } from "mobx-react"; import { computed } from "mobx"; import { FormattedTextBox } from "./FormattedTextBox"; import { ImageBox } from "./ImageBox"; -import { WebBox } from "./WebBox"; import { VideoBox } from "./VideoBox"; import { AudioBox } from "./AudioBox"; import { DocumentContentsView } from "./DocumentContentsView"; import { Transform } from "../../util/Transform"; -import { returnFalse, emptyFunction, returnOne } from "../../../Utils"; +import { returnFalse, emptyFunction } from "../../../Utils"; import { CollectionView } from "../collections/CollectionView"; import { CollectionPDFView } from "../collections/CollectionPDFView"; import { CollectionVideoView } from "../collections/CollectionVideoView"; import { IconField } from "../../../fields/IconFIeld"; import { IconBox } from "./IconBox"; -import { Opt, Doc, Field, FieldValue, FieldWaiting } from "../../../new_fields/Doc"; +import { Opt, Doc, FieldResult } from "../../../new_fields/Doc"; import { List } from "../../../new_fields/List"; +import { ImageField, VideoField, AudioField } from "../../../new_fields/URLField"; // @@ -47,7 +47,7 @@ export class FieldView extends React.Component { } @computed - get field(): FieldValue { + get field(): FieldResult { const { Document, fieldKey } = this.props; return Document[fieldKey]; } diff --git a/src/client/views/nodes/ImageBox.tsx b/src/client/views/nodes/ImageBox.tsx index 3b72e9f39..c11aee56e 100644 --- a/src/client/views/nodes/ImageBox.tsx +++ b/src/client/views/nodes/ImageBox.tsx @@ -14,16 +14,15 @@ import { createSchema, makeInterface } from '../../../new_fields/Schema'; import { DocComponent } from '../DocComponent'; import { positionSchema } from './DocumentView'; import { FieldValue, Cast } from '../../../new_fields/Types'; -import { URLField } from '../../../new_fields/URLField'; -import { Doc, FieldWaiting } from '../../../new_fields/Doc'; +import { ImageField } from '../../../new_fields/URLField'; import { List } from '../../../new_fields/List'; -const schema = createSchema({ +export const pageSchema = createSchema({ curPage: "number" }); -type ImageDocument = makeInterface<[typeof schema, typeof positionSchema]>; -const ImageDocument = makeInterface([schema, positionSchema]); +type ImageDocument = makeInterface<[typeof pageSchema, typeof positionSchema]>; +const ImageDocument = makeInterface(pageSchema, positionSchema); @observer export class ImageBox extends DocComponent(ImageDocument) { @@ -135,7 +134,7 @@ export class ImageBox extends DocComponent(ImageD } specificContextMenu = (e: React.MouseEvent): void => { - let field = Cast(this.Document[this.props.fieldKey], URLField); + let field = Cast(this.Document[this.props.fieldKey], ImageField); if (field && field !== FieldWaiting) { let url = field.url.href; ContextMenu.Instance.addItem({ @@ -167,8 +166,8 @@ export class ImageBox extends DocComponent(ImageD let field = this.Document[this.props.fieldKey]; let paths: string[] = ["http://www.cs.brown.edu/~bcz/face.gif"]; if (field === FieldWaiting) paths = ["https://image.flaticon.com/icons/svg/66/66163.svg"]; - else if (field instanceof URLField) paths = [field.url.href]; - else if (field instanceof List) paths = field.filter(val => val instanceof URLField).map(p => (p as URLField).url.href); + else if (field instanceof ImageField) paths = [field.url.href]; + else if (field instanceof List) paths = field.filter(val => val instanceof ImageField).map(p => (p as ImageField).url.href); let nativeWidth = FieldValue(this.Document.nativeWidth, 1); return (
diff --git a/src/client/views/nodes/VideoBox.tsx b/src/client/views/nodes/VideoBox.tsx index 9d7c2bc56..7b922b620 100644 --- a/src/client/views/nodes/VideoBox.tsx +++ b/src/client/views/nodes/VideoBox.tsx @@ -1,18 +1,22 @@ import React = require("react"); import { observer } from "mobx-react"; -import { FieldWaiting, Opt } from '../../../fields/Field'; -import { VideoField } from '../../../fields/VideoField'; import { FieldView, FieldViewProps } from './FieldView'; import "./VideoBox.scss"; import Measure from "react-measure"; -import { action, trace, observable, IReactionDisposer, computed, reaction } from "mobx"; -import { KeyStore } from "../../../fields/KeyStore"; -import { number } from "prop-types"; +import { action, computed } from "mobx"; +import { DocComponent } from "../DocComponent"; +import { positionSchema } from "./DocumentView"; +import { makeInterface } from "../../../new_fields/Schema"; +import { pageSchema } from "./ImageBox"; +import { Cast, FieldValue } from "../../../new_fields/Types"; +import { VideoField } from "../../../new_fields/URLField"; + +type VideoDocument = makeInterface<[typeof positionSchema, typeof pageSchema]>; +const VideoDocument = makeInterface(positionSchema, pageSchema); @observer -export class VideoBox extends React.Component { +export class VideoBox extends DocComponent(VideoDocument) { - private _reactionDisposer: Opt; private _videoRef = React.createRef(); public static LayoutString() { return FieldView.LayoutString(VideoBox); } @@ -20,7 +24,7 @@ export class VideoBox extends React.Component { super(props); } - @computed private get curPage() { return this.props.Document.GetNumber(KeyStore.CurPage, -1); } + @computed private get curPage() { return FieldValue(this.Document.curPage, -1); } _loaded: boolean = false; @@ -31,12 +35,12 @@ export class VideoBox 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); - var nativeHeight = this.props.Document.GetNumber(KeyStore.NativeHeight, 0); + var nativeWidth = FieldValue(this.Document.nativeWidth, 0); + var nativeHeight = FieldValue(this.Document.nativeHeight, 0); var newNativeHeight = nativeWidth * r.entry.height / r.entry.width; if (!nativeHeight && newNativeHeight !== nativeHeight && !isNaN(newNativeHeight)) { - this.props.Document.SetNumber(KeyStore.Height, newNativeHeight / nativeWidth * this.props.Document.GetNumber(KeyStore.Width, 0)); - this.props.Document.SetNumber(KeyStore.NativeHeight, newNativeHeight); + this.Document.height = newNativeHeight / nativeWidth * FieldValue(this.Document.width, 0); + this.Document.nativeHeight = newNativeHeight; } } else { this._loaded = true; @@ -56,12 +60,11 @@ export class VideoBox extends React.Component { } render() { - let field = this.props.Document.GetT(this.props.fieldKey, VideoField); - if (!field || field === FieldWaiting) { + let field = FieldValue(Cast(this.Document[this.props.fieldKey], VideoField)); + if (!field) { return
Loading
; } - let path = field.Data.href; - trace(); + let path = field.url.href; return ( {({ measureRef }) => diff --git a/src/client/views/nodes/WebBox.tsx b/src/client/views/nodes/WebBox.tsx index e3b6e1c05..63778fa50 100644 --- a/src/client/views/nodes/WebBox.tsx +++ b/src/client/views/nodes/WebBox.tsx @@ -4,7 +4,7 @@ import { FieldViewProps, FieldView } from './FieldView'; import { observer } from "mobx-react"; import { computed } from 'mobx'; import { HtmlField } from "../../../new_fields/HtmlField"; -import { URLField } from "../../../new_fields/URLField"; +import { WebField } from "../../../new_fields/URLField"; @observer export class WebBox extends React.Component { @@ -37,7 +37,7 @@ export class WebBox extends React.Component { let view; if (field instanceof HtmlField) { view = - } else if (field instanceof URLField) { + } else if (field instanceof WebField) { view =