diff options
Diffstat (limited to 'src/client/DocServer.ts')
-rw-r--r-- | src/client/DocServer.ts | 91 |
1 files changed, 42 insertions, 49 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index c9a30b8e3..1b0ba6bc3 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,27 +1,27 @@ -import * as io from 'socket.io-client'; -import { MessageStore, YoutubeQueryTypes, GestureContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, MobileDocumentUploadContent } from "./../server/Message"; -import { Opt, Doc, UpdatingFromServer, updateCachedAcls } from '../fields/Doc'; -import { Utils, emptyFunction } from '../Utils'; -import { SerializationHelper } from './util/SerializationHelper'; -import { RefField } from '../fields/RefField'; -import { Id, HandleUpdate, Parent } from '../fields/FieldSymbols'; -import { GestureOverlay } from './views/GestureOverlay'; -import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { runInAction } from 'mobx'; +import * as rp from 'request-promise'; +import * as io from 'socket.io-client'; +import { Doc, Opt, UpdatingFromServer } from '../fields/Doc'; +import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols'; import { ObjectField } from '../fields/ObjectField'; +import { RefField } from '../fields/RefField'; import { StrCast } from '../fields/Types'; -import * as rp from 'request-promise'; +import MobileInkOverlay from '../mobile/MobileInkOverlay'; +import { emptyFunction, Utils } from '../Utils'; +import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message'; +import { SerializationHelper } from './util/SerializationHelper'; +import { GestureOverlay } from './views/GestureOverlay'; /** * This class encapsulates the transfer and cross-client synchronization of * data stored only in documents (RefFields). In the process, it also * creates and maintains a cache of documents so that they can be accessed * more efficiently. Currently, there is no cache eviction scheme in place. - * + * * NOTE: while this class is technically abstracted to work with any [RefField], because * [Doc] instances are the only [RefField] we need / have implemented at the moment, the documentation * will treat all data used here as [Doc]s - * + * * Any time we want to write a new field to the database (via the server) * or update ourselves based on the server's update message, that occurs here */ @@ -32,12 +32,12 @@ export namespace DocServer { const strings: string[] = []; Array.from(Object.keys(_cache)).forEach(key => { const doc = _cache[key]; - if (doc instanceof Doc) strings.push(StrCast(doc.author) + " " + StrCast(doc.title) + " " + StrCast(Doc.GetT(doc, "title", "string", true))); + if (doc instanceof Doc) strings.push(StrCast(doc.author) + ' ' + StrCast(doc.title) + ' ' + StrCast(Doc.GetT(doc, 'title', 'string', true))); }); - print && strings.sort().forEach((str, i) => console.log(i.toString() + " " + str)); - rp.post(Utils.prepend("/setCacheDocumentIds"), { + print && strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); + rp.post(Utils.prepend('/setCacheDocumentIds'), { body: { - cacheDocumentIds: Array.from(Object.keys(_cache)).join(";"), + cacheDocumentIds: Array.from(Object.keys(_cache)).join(';'), }, json: true, }); @@ -50,8 +50,8 @@ export namespace DocServer { export enum WriteMode { Default = 0, //Anything goes Playground = 1, //Playground (write own/no read other updates) - LiveReadonly = 2,//Live Readonly (no write/read others) - LivePlayground = 3,//Live Playground (write own/read others) + LiveReadonly = 2, //Live Readonly (no write/read others) + LivePlayground = 3, //Live Playground (write own/read others) } const fieldWriteModes: { [field: string]: WriteMode } = {}; const docsWithUpdates: { [field: string]: Set<Doc> } = {}; @@ -62,7 +62,7 @@ export namespace DocServer { livePlaygroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.Playground)); } export function IsPlaygroundField(field: string) { - return DocServer.PlaygroundFields?.includes(field.replace(/^_/, "")); + return DocServer.PlaygroundFields?.includes(field.replace(/^_/, '')); } export function setFieldWriteMode(field: string, writeMode: WriteMode) { @@ -83,7 +83,7 @@ export namespace DocServer { export function registerDocWithCachedUpdate(doc: Doc, field: string, oldValue: any) { let list = docsWithUpdates[field]; if (!list) { - list = docsWithUpdates[field] = new Set; + list = docsWithUpdates[field] = new Set(); } if (!list.has(doc)) { Doc.AddCachedUpdate(doc, field, oldValue); @@ -92,7 +92,6 @@ export namespace DocServer { } export namespace Mobile { - export function dispatchGesturePoints(content: GestureContent) { Utils.Emit(_socket, MessageStore.GesturePoints, content); } @@ -111,17 +110,17 @@ export namespace DocServer { } } - const instructions = "This page will automatically refresh after this alert is closed. Expect to reconnect after about 30 seconds."; + const instructions = 'This page will automatically refresh after this alert is closed. Expect to reconnect after about 30 seconds.'; function alertUser(connectionTerminationReason: string) { switch (connectionTerminationReason) { - case "crash": + case 'crash': alert(`Dash has temporarily crashed. Administrators have been notified and the server is restarting itself. ${instructions}`); break; - case "temporary": + case 'temporary': alert(`An administrator has chosen to restart the server. ${instructions}`); break; - case "exit": - alert("An administrator has chosen to kill the server. Do not expect to reconnect until administrators start the server."); + case 'exit': + alert('An administrator has chosen to kill the server. Do not expect to reconnect until administrators start the server.'); break; default: console.log(`Received an unknown ConnectionTerminated message: ${connectionTerminationReason}`); @@ -132,7 +131,7 @@ export namespace DocServer { export function init(protocol: string, hostname: string, port: number, identifier: string) { _cache = {}; GUID = identifier; - protocol = protocol.startsWith("https") ? "wss" : "ws"; + protocol = protocol.startsWith('https') ? 'wss' : 'ws'; _socket = io.connect(`${protocol}://${hostname}:${port}`); // io.connect(`https://7f079dda.ngrok.io`);// if using ngrok, create a special address for the websocket @@ -153,17 +152,17 @@ export namespace DocServer { Utils.AddServerHandler(_socket, MessageStore.ConnectionTerminated, alertUser); // mobile ink overlay socket events to communicate between mobile view and desktop view - _socket.addEventListener("receiveGesturePoints", (content: GestureContent) => { + _socket.addEventListener('receiveGesturePoints', (content: GestureContent) => { MobileInkOverlay.Instance.drawStroke(content); }); - _socket.addEventListener("receiveOverlayTrigger", (content: MobileInkOverlayContent) => { + _socket.addEventListener('receiveOverlayTrigger', (content: MobileInkOverlayContent) => { GestureOverlay.Instance.enableMobileInkOverlay(content); MobileInkOverlay.Instance.initMobileInkOverlay(content); }); - _socket.addEventListener("receiveUpdateOverlayPosition", (content: UpdateMobileInkOverlayPositionContent) => { + _socket.addEventListener('receiveUpdateOverlayPosition', (content: UpdateMobileInkOverlayPositionContent) => { MobileInkOverlay.Instance.updatePosition(content); }); - _socket.addEventListener("receiveMobileDocumentUpload", (content: MobileDocumentUploadContent) => { + _socket.addEventListener('receiveMobileDocumentUpload', (content: MobileDocumentUploadContent) => { MobileInkOverlay.Instance.uploadDocument(content); }); } @@ -173,12 +172,11 @@ export namespace DocServer { } export namespace Control { - let _isReadOnly = false; export function makeReadOnly() { if (!_isReadOnly) { _isReadOnly = true; - _CreateField = field => _cache[field[Id]] = field; + _CreateField = field => (_cache[field[Id]] = field); _UpdateField = emptyFunction; _RespondToUpdate = emptyFunction; // bcz: option: don't clear RespondToUpdate to continue to receive updates as others change the DB } @@ -195,8 +193,9 @@ export namespace DocServer { } } - export function isReadOnly() { return _isReadOnly; } - + export function isReadOnly() { + return _isReadOnly; + } } /** @@ -209,7 +208,6 @@ export namespace DocServer { } export namespace Util { - /** * Emits a message to the server that wipes * all documents in the database. @@ -217,7 +215,6 @@ export namespace DocServer { export function deleteDatabase() { Utils.Emit(_socket, MessageStore.DeleteAll, {}); } - } // RETRIEVE DOCS FROM SERVER @@ -258,8 +255,7 @@ export namespace DocServer { }); cached[UpdatingFromServer] = false; return cached; - } - else if (field !== undefined) { + } else if (field !== undefined) { _cache[id] = field; } else { delete _cache[id]; @@ -272,7 +268,7 @@ export namespace DocServer { // here, indicate that the document associated with this id is currently // being retrieved and cached !force && (_cache[id] = deserializeField); - return force ? cached as any : deserializeField; + return force ? (cached as any) : deserializeField; } else if (cached instanceof Promise) { // BEING RETRIEVED AND CACHED => some other caller previously (likely recently) called GetRefField(s), // and requested the document I'm looking for. Shouldn't fetch again, just @@ -316,7 +312,6 @@ export namespace DocServer { Utils.EmitCallback(_socket, MessageStore.YoutubeApiQuery, { type: YoutubeQueryTypes.VideoDetails, videoIds: videoIds }, callBack); } - /** * Given a list of Doc GUIDs, this utility function will asynchronously attempt to each id's associated * field, first looking in the RefField cache and then communicating with @@ -381,7 +376,7 @@ export namespace DocServer { return deserialized; }); // 4) here, for each of the documents we've requested *ourselves* (i.e. weren't promises or found in the cache) - // we set the value at the field's id to a promise that will resolve to the field. + // we set the value at the field's id to a promise that will resolve to the field. // When we find that promises exist at keys in the cache, THIS is where they were set, just by some other caller (method). // The mapping in the .then call ensures that when other callers await these promises, they'll // get the resolved field @@ -391,7 +386,7 @@ export namespace DocServer { proms.push(prom); } else if (cached instanceof Promise) { proms.push(cached as any); - cached.then((f: any) => fieldMap[field.id] = f); + cached.then((f: any) => (fieldMap[field.id] = f)); } else if (field) { proms.push(cached as any); fieldMap[field.id] = DocServer.GetCachedRefField(field.id) || field; @@ -413,20 +408,19 @@ export namespace DocServer { const field = fields[id]; map[id] = field; }); - } // 7) those promises we encountered in the else if of 1), which represent // other callers having already submitted a request to the server for (a) document(s) // in which we're interested, must still be awaited so that we can return the proper - // values for those as well. + // values for those as well. // // fortunately, those other callers will also hit their own version of 6) and clean up // the shared cache when these promises resolve, so all we have to do is... const otherCallersFetching = await Promise.all(promises); // ...extract the RefFields returned from the resolution of those promises and add them to our // own map. - waitingIds.forEach((id, index) => map[id] = otherCallersFetching[index]); + waitingIds.forEach((id, index) => (map[id] = otherCallersFetching[index])); // now, we return our completed mapping from all of the ids that were passed into the method // to their actual RefField | undefined values. This return value either becomes the input @@ -476,7 +470,7 @@ export namespace DocServer { } function _UpdateFieldImpl(id: string, diff: any) { - (!DocServer.Control.isReadOnly()) && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); + !DocServer.Control.isReadOnly() && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); } let _UpdateField: (id: string, diff: any) => void = errorFunc; @@ -520,12 +514,11 @@ export namespace DocServer { Utils.Emit(_socket, MessageStore.DeleteFields, ids); } - function _respondToDeleteImpl(ids: string | string[]) { function deleteId(id: string) { delete _cache[id]; } - if (typeof ids === "string") { + if (typeof ids === 'string') { deleteId(ids); } else if (Array.isArray(ids)) { ids.map(deleteId); |