aboutsummaryrefslogtreecommitdiff
path: root/src/new_fields
diff options
context:
space:
mode:
Diffstat (limited to 'src/new_fields')
-rw-r--r--src/new_fields/Doc.ts16
-rw-r--r--src/new_fields/IconField.ts6
-rw-r--r--src/new_fields/List.ts192
-rw-r--r--src/new_fields/util.ts8
4 files changed, 181 insertions, 41 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts
index d15b6309d..0e5105761 100644
--- a/src/new_fields/Doc.ts
+++ b/src/new_fields/Doc.ts
@@ -3,8 +3,8 @@ import { serializable, primitive, map, alias, list } from "serializr";
import { autoObject, SerializationHelper, Deserializable } from "../client/util/SerializationHelper";
import { Utils } from "../Utils";
import { DocServer } from "../client/DocServer";
-import { setter, getter, getField, updateFunction } from "./util";
-import { Cast, ToConstructor, PromiseValue, FieldValue } from "./Types";
+import { setter, getter, getField, updateFunction, deleteProperty } from "./util";
+import { Cast, ToConstructor, PromiseValue, FieldValue, NumCast } from "./Types";
import { UndoManager, undoBatch } from "../client/util/UndoManager";
import { listSpec } from "./Schema";
import { List } from "./List";
@@ -25,6 +25,8 @@ export type FieldResult<T extends Field = Field> = Opt<T> | FieldWaiting<Extract
export const Update = Symbol("Update");
export const Self = Symbol("Self");
+export const WidthSym = Symbol("Width");
+export const HeightSym = Symbol("Height");
@Deserializable("doc").withFields(["id"])
export class Doc extends RefField {
@@ -34,7 +36,7 @@ export class Doc extends RefField {
set: setter,
get: getter,
ownKeys: target => Object.keys(target.__fields),
- deleteProperty: () => { throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); },
+ deleteProperty: deleteProperty,
defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); },
});
if (!id || forceSave) {
@@ -70,6 +72,8 @@ export class Doc extends RefField {
}
private [Self] = this;
+ public [WidthSym] = () => { return NumCast(this.__fields.width); } // bcz: is this the right way to access width/height? it didn't work with : this.width
+ public [HeightSym] = () => { return NumCast(this.__fields.height); }
}
export namespace Doc {
@@ -151,8 +155,8 @@ export namespace Doc {
}
export function MakeLink(source: Doc, target: Doc): Doc {
- let linkDoc = new Doc;
- UndoManager.RunInBatch(() => {
+ return UndoManager.RunInBatch(() => {
+ let linkDoc = new Doc;
linkDoc.title = "New Link";
linkDoc.linkDescription = "";
linkDoc.linkTags = "Default";
@@ -171,8 +175,8 @@ export namespace Doc {
source.linkedToDocs = linkedTo = new List<Doc>();
}
linkedTo.push(linkDoc);
+ return linkDoc;
}, "make link");
- return linkDoc;
}
export function MakeDelegate(doc: Doc): Doc;
diff --git a/src/new_fields/IconField.ts b/src/new_fields/IconField.ts
index 46f111f8e..c79a2f79a 100644
--- a/src/new_fields/IconField.ts
+++ b/src/new_fields/IconField.ts
@@ -5,10 +5,10 @@ import { ObjectField } from "./ObjectField";
@Deserializable("icon")
export class IconField extends ObjectField {
@serializable(primitive())
- readonly layout: string;
+ readonly icon: string;
- constructor(layout: string) {
+ constructor(icon: string) {
super();
- this.layout = layout;
+ this.icon = icon;
}
}
diff --git a/src/new_fields/List.ts b/src/new_fields/List.ts
index e4a80f7a1..ec1bf44a9 100644
--- a/src/new_fields/List.ts
+++ b/src/new_fields/List.ts
@@ -1,21 +1,173 @@
import { Deserializable, autoObject } from "../client/util/SerializationHelper";
import { Field, Update, Self } from "./Doc";
-import { setter, getter } from "./util";
+import { setter, getter, deleteProperty } from "./util";
import { serializable, alias, list } from "serializr";
import { observable, observe, IArrayChange, IArraySplice, IObservableArray, Lambda, reaction } from "mobx";
import { ObjectField, OnUpdate } from "./ObjectField";
+import { RefField } from "./RefField";
+import { ProxyField } from "./Proxy";
const listHandlers: any = {
- push(...items: any[]) {
- // console.log("push");
- // console.log(...items);
- return this[Self].__fields.push(...items);
+ /// Mutator methods
+ copyWithin() {
+ throw new Error("copyWithin not supported yet");
+ },
+ fill(value: any, start?: number, end?: number) {
+ if (value instanceof RefField) {
+ throw new Error("fill with RefFields not supported yet");
+ }
+ const res = this[Self].__fields.fill(value, start, end);
+ this[Update]();
+ return res;
},
pop(): any {
- return this[Self].__fields.pop();
+ const field = toRealField(this[Self].__fields.pop());
+ this[Update]();
+ return field;
+ },
+ push(...items: any[]) {
+ items = items.map(toObjectField);
+ const res = this[Self].__fields.push(...items);
+ this[Update]();
+ return res;
+ },
+ reverse() {
+ const res = this[Self].__fields.reverse();
+ this[Update]();
+ return res;
+ },
+ shift() {
+ const res = toRealField(this[Self].__fields.shift());
+ this[Update]();
+ return res;
+ },
+ sort(cmpFunc: any) {
+ const res = this[Self].__fields.sort(cmpFunc ? (first: any, second: any) => cmpFunc(toRealField(first), toRealField(second)) : undefined);
+ this[Update]();
+ return res;
+ },
+ splice(start: number, deleteCount: number, ...items: any[]) {
+ items = items.map(toObjectField);
+ const res = this[Self].__fields.splice(start, deleteCount, ...items);
+ this[Update]();
+ return res.map(toRealField);
+ },
+ unshift(...items: any[]) {
+ items = items.map(toObjectField);
+ const res = this[Self].__fields.unshift(...items);
+ this[Update]();
+ return res;
+
+ },
+ /// Accessor methods
+ concat(...items: any[]) {
+ return this[Self].__fields.map(toRealField).concat(...items);
+ },
+ includes(valueToFind: any, fromIndex: number) {
+ const fields = this[Self].__fields;
+ if (valueToFind instanceof RefField) {
+ return fields.map(toRealField).includes(valueToFind, fromIndex);
+ } else {
+ return fields.includes(valueToFind, fromIndex);
+ }
+ },
+ indexOf(valueToFind: any, fromIndex: number) {
+ const fields = this[Self].__fields;
+ if (valueToFind instanceof RefField) {
+ return fields.map(toRealField).indexOf(valueToFind, fromIndex);
+ } else {
+ return fields.indexOf(valueToFind, fromIndex);
+ }
+ },
+ join(separator: any) {
+ return this[Self].__fields.map(toRealField).join(separator);
+ },
+ lastIndexOf(valueToFind: any, fromIndex: number) {
+ const fields = this[Self].__fields;
+ if (valueToFind instanceof RefField) {
+ return fields.map(toRealField).lastIndexOf(valueToFind, fromIndex);
+ } else {
+ return fields.lastIndexOf(valueToFind, fromIndex);
+ }
+ },
+ slice(begin: number, end: number) {
+ return this[Self].__fields.slice(begin, end).map(toRealField);
+ },
+
+ /// Iteration methods
+ entries() {
+ return this[Self].__fields.map(toRealField).entries();
+ },
+ every(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).every(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.every((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ filter(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).filter(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.filter((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ find(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).find(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.find((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ findIndex(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).findIndex(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.findIndex((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ forEach(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).forEach(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.forEach((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ map(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).map(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.map((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ reduce(callback: any, initialValue: any) {
+ return this[Self].__fields.map(toRealField).reduce(callback, initialValue);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.reduce((acc:any, element:any, index:number, array:any) => callback(acc, toRealField(element), index, array), initialValue);
+ },
+ reduceRight(callback: any, initialValue: any) {
+ return this[Self].__fields.map(toRealField).reduceRight(callback, initialValue);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.reduceRight((acc:any, element:any, index:number, array:any) => callback(acc, toRealField(element), index, array), initialValue);
+ },
+ some(callback: any, thisArg: any) {
+ return this[Self].__fields.map(toRealField).some(callback, thisArg);
+ // TODO This is probably more efficient, but technically the callback can take the array, which would mean we would have to map the actual array anyway.
+ // If we don't want to support the array parameter, we should use this version instead
+ // return this[Self].__fields.some((element:any, index:number, array:any) => callback(toRealField(element), index, array), thisArg);
+ },
+ values() {
+ return this[Self].__fields.map(toRealField).values();
+ },
+ [Symbol.iterator]() {
+ return this[Self].__fields.map(toRealField).values();
}
};
+function toObjectField(field: Field) {
+ return field instanceof RefField ? new ProxyField(field) : field;
+}
+
+function toRealField(field: Field) {
+ return field instanceof ProxyField ? field.value() : field;
+}
+
function listGetter(target: any, prop: string | number | symbol, receiver: any): any {
if (listHandlers.hasOwnProperty(prop)) {
return listHandlers[prop];
@@ -38,36 +190,15 @@ interface ListIndexUpdate<T> {
type ListUpdate<T> = ListSpliceUpdate<T> | ListIndexUpdate<T>;
-const ObserveDisposer = Symbol("Observe Disposer");
-
-function listObserver<T extends Field>(this: ListImpl<T>, change: IArrayChange<T> | IArraySplice<T>) {
- if (change.type === "splice") {
- this[Update]({
- index: change.index,
- removedCount: change.removedCount,
- added: change.added,
- type: change.type
- });
- } else {
- //This should already be handled by the getter for the Proxy
- // this[Update]({
- // index: change.index,
- // newValue: change.newValue,
- // type: change.type
- // });
- }
-}
-
@Deserializable("list")
class ListImpl<T extends Field> extends ObjectField {
constructor(fields: T[] = []) {
super();
this.___fields = fields;
- this[ObserveDisposer] = observe(this.__fields as IObservableArray<T>, listObserver.bind(this));
const list = new Proxy<this>(this, {
set: setter,
- get: getter,
- deleteProperty: () => { throw new Error("Currently properties can't be deleted from documents, assign to undefined instead"); },
+ get: listGetter,
+ deleteProperty: deleteProperty,
defineProperty: () => { throw new Error("Currently properties can't be defined on documents using Object.defineProperty"); },
});
return list;
@@ -82,8 +213,6 @@ class ListImpl<T extends Field> extends ObjectField {
private set __fields(value) {
this.___fields = value;
- this[ObserveDisposer]();
- this[ObserveDisposer] = observe(this.__fields as IObservableArray<T>, listObserver.bind(this));
}
// @serializable(alias("fields", list(autoObject())))
@@ -97,7 +226,6 @@ class ListImpl<T extends Field> extends ObjectField {
update && update();
}
- private [ObserveDisposer]: Lambda;
private [Self] = this;
}
export type List<T extends Field> = ListImpl<T> & T[];
diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts
index 511820115..128817ab8 100644
--- a/src/new_fields/util.ts
+++ b/src/new_fields/util.ts
@@ -78,6 +78,14 @@ export function getField(target: any, prop: string | number, ignoreProto: boolea
return field;
}
+export function deleteProperty(target: any, prop: string | number | symbol) {
+ if (typeof prop === "symbol") {
+ delete target[prop];
+ return true;
+ }
+ throw new Error("Currently properties can't be deleted from documents, assign to undefined instead");
+}
+
export function updateFunction(target: any, prop: any, value: any) {
return (diff?: any) => {
if (!diff) diff = { '$set': { ["fields." + prop]: SerializationHelper.Serialize(value) } };