From e3ad2c2c8f920a5538541b8e495af52815e36dc6 Mon Sep 17 00:00:00 2001 From: Tyler Schicke Date: Fri, 19 Apr 2019 23:52:34 -0400 Subject: Started fixing stuff --- src/client/views/DocComponent.tsx | 14 ++++++ src/client/views/nodes/DocumentView.tsx | 87 ++++++++++----------------------- src/new_fields/Doc.ts | 8 +++ src/new_fields/Schema.ts | 7 +-- src/new_fields/Types.ts | 2 +- 5 files changed, 54 insertions(+), 64 deletions(-) create mode 100644 src/client/views/DocComponent.tsx (limited to 'src') diff --git a/src/client/views/DocComponent.tsx b/src/client/views/DocComponent.tsx new file mode 100644 index 000000000..31282744b --- /dev/null +++ b/src/client/views/DocComponent.tsx @@ -0,0 +1,14 @@ +import * as React from 'react'; +import { Doc } from '../../new_fields/Doc'; +import { computed } from 'mobx'; + +export function DocComponent

(schemaCtor: (doc: Doc) => T) { + class Component extends React.Component

{ + //TODO This might be pretty inefficient if doc isn't observed, because computed doesn't cache then + @computed + get Document() { + return schemaCtor(this.props.Document); + } + } + return Component; +} \ No newline at end of file diff --git a/src/client/views/nodes/DocumentView.tsx b/src/client/views/nodes/DocumentView.tsx index b99e449be..4f7909692 100644 --- a/src/client/views/nodes/DocumentView.tsx +++ b/src/client/views/nodes/DocumentView.tsx @@ -1,12 +1,5 @@ import { action, computed, runInAction } from "mobx"; import { observer } from "mobx-react"; -import { BooleanField } from "../../../fields/BooleanField"; -import { Document } from "../../../fields/Document"; -import { Field, FieldWaiting, Opt } from "../../../fields/Field"; -import { Key } from "../../../fields/Key"; -import { KeyStore } from "../../../fields/KeyStore"; -import { ListField } from "../../../fields/ListField"; -import { TextField } from "../../../fields/TextField"; import { ServerUtils } from "../../../server/ServerUtil"; import { emptyFunction, Utils } from "../../../Utils"; import { Documents } from "../../documents/Documents"; @@ -23,11 +16,15 @@ import { ContextMenu } from "../ContextMenu"; import { DocumentContentsView } from "./DocumentContentsView"; import "./DocumentView.scss"; import React = require("react"); +import { Field, Opt, Doc, Id } from "../../../new_fields/Doc"; +import { DocComponent } from "../DocComponent"; +import { createSchema, makeInterface } from "../../../new_fields/Schema"; +import { FieldValue } from "../../../new_fields/Types"; export interface DocumentViewProps { ContainingCollectionView: Opt; - Document: Document; + Document: Doc; addDocument?: (doc: Document, allowDuplicates?: boolean) => boolean; removeDocument?: (doc: Document) => boolean; moveDocument?: (doc: Document, targetCollection: Document, addDocument: (document: Document) => boolean) => boolean; @@ -41,48 +38,20 @@ export interface DocumentViewProps { parentActive: () => boolean; onActiveChanged: (isActive: boolean) => void; } -export interface JsxArgs extends DocumentViewProps { - Keys: { [name: string]: Key }; - Fields: { [name: string]: Field }; -} -/* -This function is pretty much a hack that lets us fill out the fields in JsxArgs with something that -jsx-to-string can recover the jsx from -Example usage of this function: - public static LayoutString() { - let args = FakeJsxArgs(["Data"]); - return jsxToString( - , - { useFunctionCode: true, functionNameOnly: true } - ) - } -*/ -export function FakeJsxArgs(keys: string[], fields: string[] = []): JsxArgs { - let Keys: { [name: string]: any } = {}; - let Fields: { [name: string]: any } = {}; - for (const key of keys) { - Object.defineProperty(emptyFunction, "name", { value: key + "Key" }); - Keys[key] = emptyFunction; - } - for (const field of fields) { - Object.defineProperty(emptyFunction, "name", { value: field }); - Fields[field] = emptyFunction; - } - let args: JsxArgs = { - Document: function Document() { }, - DocumentView: function DocumentView() { }, - Keys, - Fields - } as any; - return args; -} +const schema = createSchema({ + layout: "string", + minimized: "boolean", + nativeWidth: "number", + nativeHeight: "number", + backgroundColor: "string" +}); + +type Document = makeInterface; +const Document = makeInterface(schema); @observer -export class DocumentView extends React.Component { +export class DocumentView extends DocComponent(Document) { private _downX: number = 0; private _downY: number = 0; private _mainCont = React.createRef(); @@ -91,9 +60,6 @@ export class DocumentView extends React.Component { public get ContentDiv() { return this._mainCont.current; } @computed get active(): boolean { return SelectionManager.IsSelected(this) || this.props.parentActive(); } @computed get topMost(): boolean { return this.props.isTopMost; } - @computed get layout(): string { return this.props.Document.GetText(KeyStore.Layout, "

Error loading layout data

"); } - @computed get layoutKeys(): Key[] { return this.props.Document.GetData(KeyStore.LayoutKeys, ListField, new Array()); } - @computed get layoutFields(): Key[] { return this.props.Document.GetData(KeyStore.LayoutFields, ListField, new Array()); } onPointerDown = (e: React.PointerEvent): void => { this._downX = e.clientX; @@ -200,7 +166,7 @@ export class DocumentView extends React.Component { } } fullScreenClicked = (e: React.MouseEvent): void => { - CollectionDockingView.Instance.OpenFullScreen((this.props.Document.GetPrototype() as Document).MakeDelegate()); + CollectionDockingView.Instance.OpenFullScreen(Doc.MakeDelegate(this.Document.prototype)); ContextMenu.Instance.clearItems(); ContextMenu.Instance.addItem({ description: "Close Full Screen", event: this.closeFullScreenClicked }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); @@ -266,9 +232,9 @@ export class DocumentView extends React.Component { onDrop = (e: React.DragEvent) => { let text = e.dataTransfer.getData("text/plain"); if (!e.isDefaultPrevented() && text && text.startsWith(" { 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(ServerUtils.prepend("/doc/" + this.props.Document.Id)) }); - ContextMenu.Instance.addItem({ description: "Copy ID", event: () => Utils.CopyText(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 }); ContextMenu.Instance.displayMenu(e.pageX - 15, e.pageY - 15); - if (!SelectionManager.IsSelected(this)) + if (!SelectionManager.IsSelected(this)) { SelectionManager.SelectDoc(this, false); + } } @action - expand = () => this.props.Document.SetBoolean(KeyStore.Minimized, false) - isMinimized = () => this.props.Document.GetBoolean(KeyStore.Minimized, false); + expand = () => this.Document.minimized = false + isMinimized = () => FieldValue(this.Document.minimized) || false; isSelected = () => SelectionManager.IsSelected(this); select = (ctrlPressed: boolean) => SelectionManager.SelectDoc(this, ctrlPressed); - @computed get nativeWidth() { return this.props.Document.GetNumber(KeyStore.NativeWidth, 0); } - @computed get nativeHeight() { return this.props.Document.GetNumber(KeyStore.NativeHeight, 0); } + @computed get nativeWidth() { return FieldValue(this.Document.nativeWidth) || 0; } + @computed get nativeHeight() { return FieldValue(this.Document.nativeHeight) || 0; } @computed get contents() { return (); } render() { @@ -321,7 +288,7 @@ export class DocumentView extends React.Component {
(doc: Doc, key: string, ctor: FieldCtor, ignoreProto: boolean = false): Field | null | undefined { return Cast(Get(doc, key, ignoreProto), ctor); } + export function MakeDelegate(doc: Opt): Opt { + if (!doc) { + return undefined; + } + const delegate = new Doc(); + delegate.prototype = doc; + return delegate; + } export const Prototype = Symbol("Prototype"); } diff --git a/src/new_fields/Schema.ts b/src/new_fields/Schema.ts index c7d2f0801..27b9635af 100644 --- a/src/new_fields/Schema.ts +++ b/src/new_fields/Schema.ts @@ -1,4 +1,4 @@ -import { Interface, ToInterface, Cast } from "./Types"; +import { Interface, ToInterface, Cast, FieldCtor, ToConstructor } from "./Types"; import { Doc } from "./Doc"; export type makeInterface = Partial> & Doc; @@ -42,6 +42,7 @@ export function makeStrictInterface(schema: T): (doc: Doc) }; } -export function createSchema(schema: T): T { - return schema; +export function createSchema(schema: T): T & { prototype: ToConstructor } { + schema.prototype = Doc; + return schema as any; } diff --git a/src/new_fields/Types.ts b/src/new_fields/Types.ts index 416298a64..cafb208ce 100644 --- a/src/new_fields/Types.ts +++ b/src/new_fields/Types.ts @@ -53,6 +53,6 @@ export function Cast>(field: Field | null | undefined return undefined; } -export function FieldValue(field: Opt | Promise>): Opt { +export function FieldValue(field: Opt | Promise>): Opt { return field instanceof Promise ? undefined : field; } -- cgit v1.2.3-70-g09d2