diff options
Diffstat (limited to 'src/new_fields')
-rw-r--r-- | src/new_fields/Doc.ts | 43 | ||||
-rw-r--r-- | src/new_fields/util.ts | 38 |
2 files changed, 50 insertions, 31 deletions
diff --git a/src/new_fields/Doc.ts b/src/new_fields/Doc.ts index ba01cfd9c..543ee46cc 100644 --- a/src/new_fields/Doc.ts +++ b/src/new_fields/Doc.ts @@ -13,6 +13,7 @@ import { List } from "./List"; import { DocumentType } from "../client/documents/Documents"; import { ComputedField, ScriptField } from "./ScriptField"; import { PrefetchProxy, ProxyField } from "./Proxy"; +import { CurrentUserUtils } from "../server/authentication/models/current_user_utils"; export namespace Field { export function toKeyValueString(doc: Doc, key: string): string { @@ -68,6 +69,7 @@ export function DocListCast(field: FieldResult): Doc[] { export const WidthSym = Symbol("Width"); export const HeightSym = Symbol("Height"); +export const UpdatingFromServer = Symbol("UpdatingFromServer"); const CachedUpdates = Symbol("Cached updates"); function fetchProto(doc: Doc) { @@ -77,8 +79,6 @@ function fetchProto(doc: Doc) { } } -let updatingFromServer = false; - @scriptingGlobal @Deserializable("Doc", fetchProto).withFields(["id"]) export class Doc extends RefField { @@ -132,8 +132,10 @@ export class Doc extends RefField { //{ [key: string]: Field | FieldWaiting | undefined } private ___fields: any = {}; + private [UpdatingFromServer]: boolean = false; + private [Update] = (diff: any) => { - if (updatingFromServer) { + if (this[UpdatingFromServer]) { return; } DocServer.UpdateField(this[Id], diff); @@ -148,10 +150,11 @@ export class Doc extends RefField { return "invalid"; } - private [CachedUpdates]: { [key: string]: () => Promise<any> } = {}; + private [CachedUpdates]: { [key: string]: () => void | Promise<any> } = {}; public async [HandleUpdate](diff: any) { const set = diff.$set; + const sameAuthor = this.author === CurrentUserUtils.email; if (set) { for (const key in set) { if (!key.startsWith("fields.")) { @@ -160,14 +163,15 @@ export class Doc extends RefField { const fKey = key.substring(7); const fn = async () => { const value = await SerializationHelper.Deserialize(set[key]); - updatingFromServer = true; + this[UpdatingFromServer] = true; this[fKey] = value; - updatingFromServer = false; + this[UpdatingFromServer] = false; }; - if (DocServer.getFieldWriteMode(fKey)) { - this[CachedUpdates][fKey] = fn; - } else { + if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) { + delete this[CachedUpdates][fKey]; await fn(); + } else { + this[CachedUpdates][fKey] = fn; } } } @@ -178,15 +182,16 @@ export class Doc extends RefField { continue; } const fKey = key.substring(7); - const fn = async () => { - updatingFromServer = true; + const fn = () => { + this[UpdatingFromServer] = true; delete this[fKey]; - updatingFromServer = false; + this[UpdatingFromServer] = false; }; - if (DocServer.getFieldWriteMode(fKey)) { - this[CachedUpdates][fKey] = fn; - } else { + if (sameAuthor || DocServer.getFieldWriteMode(fKey) !== DocServer.WriteMode.Playground) { + delete this[CachedUpdates][fKey]; await fn(); + } else { + this[CachedUpdates][fKey] = fn; } } } @@ -211,6 +216,14 @@ export namespace Doc { delete doc[CachedUpdates][field]; } } + export function AddCachedUpdate(doc: Doc, field: string, oldValue: any) { + const val = oldValue; + doc[CachedUpdates][field] = () => { + doc[UpdatingFromServer] = true; + doc[field] = val; + doc[UpdatingFromServer] = false; + }; + } export function MakeReadOnly(): { end(): void } { makeReadOnly(); return { diff --git a/src/new_fields/util.ts b/src/new_fields/util.ts index 099fe2d0a..c546e2aac 100644 --- a/src/new_fields/util.ts +++ b/src/new_fields/util.ts @@ -1,5 +1,5 @@ import { UndoManager } from "../client/util/UndoManager"; -import { Doc, Field, FieldResult } from "./Doc"; +import { Doc, Field, FieldResult, UpdatingFromServer } from "./Doc"; import { SerializationHelper } from "../client/util/SerializationHelper"; import { ProxyField } from "./Proxy"; import { RefField } from "./RefField"; @@ -59,23 +59,29 @@ const _setterImpl = action(function (target: any, prop: string | symbol | number delete curValue[Parent]; delete curValue[OnUpdate]; } - if (value === undefined) { - delete target.__fields[prop]; - } else { - target.__fields[prop] = value; - } const writeMode = DocServer.getFieldWriteMode(prop as string); - if (typeof value === "object" && !(value instanceof ObjectField)) debugger; - if (!writeMode || (writeMode === DocServer.WriteMode.SameUser && receiver.author === CurrentUserUtils.email)) { - if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } }); - else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } }); - } else { - DocServer.registerDocWithCachedUpdate(receiver, prop as string); + const fromServer = target[UpdatingFromServer]; + const sameAuthor = fromServer || (receiver.author === CurrentUserUtils.email); + const writeToDoc = sameAuthor || (writeMode !== DocServer.WriteMode.LiveReadonly); + const writeToServer = sameAuthor || (writeMode === DocServer.WriteMode.Default); + if (writeToDoc) { + if (value === undefined) { + delete target.__fields[prop]; + } else { + target.__fields[prop] = value; + } + if (typeof value === "object" && !(value instanceof ObjectField)) debugger; + if (writeToServer) { + if (value === undefined) target[Update]({ '$unset': { ["fields." + prop]: "" } }); + else target[Update]({ '$set': { ["fields." + prop]: value instanceof ObjectField ? SerializationHelper.Serialize(value) : (value === undefined ? null : value) } }); + } else { + DocServer.registerDocWithCachedUpdate(receiver, prop as string, curValue); + } + UndoManager.AddEvent({ + redo: () => receiver[prop] = value, + undo: () => receiver[prop] = curValue + }); } - UndoManager.AddEvent({ - redo: () => receiver[prop] = value, - undo: () => receiver[prop] = curValue - }); return true; }); |