diff options
Diffstat (limited to 'src/client/DocServer.ts')
-rw-r--r-- | src/client/DocServer.ts | 88 |
1 files changed, 54 insertions, 34 deletions
diff --git a/src/client/DocServer.ts b/src/client/DocServer.ts index 02b047a95..53c7b857a 100644 --- a/src/client/DocServer.ts +++ b/src/client/DocServer.ts @@ -1,16 +1,18 @@ import { runInAction } from 'mobx'; import * as rp from 'request-promise'; import * as io from 'socket.io-client'; -import { Doc, Opt } from '../fields/Doc'; +import { Doc, DocListCast, Opt } from '../fields/Doc'; import { UpdatingFromServer } from '../fields/DocSymbols'; import { FieldLoader } from '../fields/FieldLoader'; import { HandleUpdate, Id, Parent } from '../fields/FieldSymbols'; import { ObjectField } from '../fields/ObjectField'; import { RefField } from '../fields/RefField'; -import { StrCast } from '../fields/Types'; +import { DocCast, StrCast } from '../fields/Types'; import MobileInkOverlay from '../mobile/MobileInkOverlay'; import { emptyFunction, Utils } from '../Utils'; import { GestureContent, MessageStore, MobileDocumentUploadContent, MobileInkOverlayContent, UpdateMobileInkOverlayPositionContent, YoutubeQueryTypes } from './../server/Message'; +import { DocumentType } from './documents/DocumentTypes'; +import { LinkManager } from './util/LinkManager'; import { SerializationHelper } from './util/SerializationHelper'; import { GestureOverlay } from './views/GestureOverlay'; @@ -30,38 +32,51 @@ import { GestureOverlay } from './views/GestureOverlay'; export namespace DocServer { let _cache: { [id: string]: RefField | Promise<Opt<RefField>> } = {}; - export function QUERY_SERVER_CACHE(title: string) { + export function FindDocByTitle(title: string) { const foundDocId = Array.from(Object.keys(_cache)) .filter(key => _cache[key] instanceof Doc) .find(key => (_cache[key] as Doc).title === title); return foundDocId ? (_cache[foundDocId] as Doc) : undefined; } - export function UPDATE_SERVER_CACHE(print: boolean = false) { - if (print) { - 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))); - }); - strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); - } - const filtered = Array.from(Object.keys(_cache)).filter(key => { - const doc = _cache[key] as Doc; - if (!(StrCast(doc.author).includes('.edu') || StrCast(doc.author).includes('.com')) || doc.author == Doc.CurrentUserEmail) return true; - return false; + let cacheDocumentIds = ''; // ; separate string of all documents ids in the user's working set (cached on the server) + export let CacheNeedsUpdate = false; + export function UPDATE_SERVER_CACHE() { + const prototypes = Object.values(DocumentType) + .filter(type => type !== DocumentType.NONE) + .map(type => _cache[type + 'Proto']) + .filter(doc => doc instanceof Doc) + .map(doc => doc as Doc); + const references = new Set<Doc>(prototypes); + Doc.FindReferences(Doc.UserDoc(), references, undefined); + DocListCast(DocCast(Doc.UserDoc().myLinkDatabase).data).forEach(link => { + if (!references.has(DocCast(link.link_anchor_1)) && !references.has(DocCast(link.link_anchor_2))) { + Doc.RemoveDocFromList(DocCast(Doc.UserDoc().myLinkDatabase), 'data', link); + } }); + LinkManager.userLinkDBs.forEach(linkDb => Doc.FindReferences(linkDb, references, undefined)); + const filtered = Array.from(references); + + const newCacheUpdate = filtered.map(doc => doc[Id]).join(';'); + if (newCacheUpdate === cacheDocumentIds) return; + cacheDocumentIds = newCacheUpdate; + + // print out cached docs + console.log('Set cached docs = '); + const is_filtered = filtered.filter(doc => !Doc.IsSystem(doc)); + const strings = is_filtered.map(doc => StrCast(doc.title) + ' ' + (Doc.IsDataProto(doc) ? '(data)' : '(embedding)')); + strings.sort().forEach((str, i) => console.log(i.toString() + ' ' + str)); rp.post(Utils.prepend('/setCacheDocumentIds'), { body: { - cacheDocumentIds: filtered.join(';'), + cacheDocumentIds, }, json: true, }); } export let _socket: SocketIOClient.Socket; // this client's distinct GUID created at initialization - let GUID: string; + let USER_ID: string; // indicates whether or not a document is currently being udpated, and, if so, its id export enum WriteMode { @@ -73,10 +88,14 @@ export namespace DocServer { const fieldWriteModes: { [field: string]: WriteMode } = {}; const docsWithUpdates: { [field: string]: Set<Doc> } = {}; - export var PlaygroundFields: string[]; - export function setPlaygroundFields(livePlaygroundFields: string[]) { - DocServer.PlaygroundFields = livePlaygroundFields; - livePlaygroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.Playground)); + export var PlaygroundFields: string[] = []; + export function setLivePlaygroundFields(livePlaygroundFields: string[]) { + DocServer.PlaygroundFields.push(...livePlaygroundFields); + livePlaygroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.LivePlayground)); + } + export function setPlaygroundFields(playgroundFields: string[]) { + DocServer.PlaygroundFields.push(...playgroundFields); + playgroundFields.forEach(f => DocServer.setFieldWriteMode(f, DocServer.WriteMode.Playground)); } export function IsPlaygroundField(field: string) { return DocServer.PlaygroundFields?.includes(field.replace(/^_/, '')); @@ -94,7 +113,7 @@ export namespace DocServer { } export function getFieldWriteMode(field: string) { - return Doc.CurrentUserEmail === 'guest' ? WriteMode.LiveReadonly : fieldWriteModes[field] || WriteMode.Default; + return Doc.CurrentUserEmail === 'guest' ? WriteMode.LivePlayground : fieldWriteModes[field] || WriteMode.Default; } export function registerDocWithCachedUpdate(doc: Doc, field: string, oldValue: any) { @@ -147,9 +166,9 @@ export namespace DocServer { export function init(protocol: string, hostname: string, port: number, identifier: string) { _cache = {}; - GUID = identifier; + USER_ID = identifier; protocol = protocol.startsWith('https') ? 'wss' : 'ws'; - _socket = io.connect(`${protocol}://${hostname}:${port}`); + _socket = require('socket.io-client')(`${protocol}://${hostname}:${port}`, { transports: ['websocket'], rejectUnauthorized: false }); // io.connect(`https://7f079dda.ngrok.io`);// if using ngrok, create a special address for the websocket _GetCachedRefField = _GetCachedRefFieldImpl; @@ -200,7 +219,7 @@ export namespace DocServer { } export function makeEditable() { - if (_isReadOnly) { + if (Control.isReadOnly()) { location.reload(); // _isReadOnly = false; // _CreateField = _CreateFieldImpl; @@ -221,7 +240,7 @@ export namespace DocServer { * indicating that this client has connected */ function onConnection() { - _socket.emit(MessageStore.Bar.Message, GUID); + _socket.emit(MessageStore.Bar.Message, USER_ID); } export namespace Util { @@ -345,7 +364,7 @@ export namespace DocServer { // i) which documents need to be fetched // ii) which are already in the process of being fetched // iii) which already exist in the cache - for (const id of ids) { + for (const id of ids.filter(id => id)) { const cached = _cache[id]; if (cached === undefined) { defaultPromises.push({ @@ -374,7 +393,7 @@ export namespace DocServer { // fields for the given ids. This returns a promise, which, when resolved, indicates that all the JSON serialized versions of // the fields have been returned from the server console.log('Requesting ' + requestedIds.length); - FieldLoader.active && runInAction(() => (FieldLoader.ServerLoadStatus.requested = requestedIds.length)); + setTimeout(() => runInAction(() => (FieldLoader.ServerLoadStatus.requested = requestedIds.length))); const serializedFields = await Utils.EmitCallback(_socket, MessageStore.GetRefFields, requestedIds); // 3) when the serialized RefFields have been received, go head and begin deserializing them into objects. @@ -384,7 +403,7 @@ export namespace DocServer { console.log('deserializing ' + serializedFields.length + ' fields'); for (const field of serializedFields) { processed++; - if (FieldLoader.active && processed % 150 === 0) { + if (processed % 150 === 0) { runInAction(() => (FieldLoader.ServerLoadStatus.retrieved = processed)); await new Promise(res => setTimeout(res)); // force loading to yield to splash screen rendering to update progress } @@ -470,13 +489,14 @@ export namespace DocServer { * @param field the [RefField] to be serialized and sent to the server to be stored in the database */ export function CreateField(field: RefField) { + CacheNeedsUpdate = true; _CreateField(field); } function _CreateFieldImpl(field: RefField) { _cache[field[Id]] = field; const initialState = SerializationHelper.Serialize(field); - Utils.Emit(_socket, MessageStore.CreateField, initialState); + Doc.CurrentUserEmail !== 'guest' && Utils.Emit(_socket, MessageStore.CreateField, initialState); } let _CreateField: (field: RefField) => void = errorFunc; @@ -496,7 +516,7 @@ export namespace DocServer { } function _UpdateFieldImpl(id: string, diff: any) { - !DocServer.Control.isReadOnly() && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); + !DocServer.Control.isReadOnly() && Doc.CurrentUserEmail !== 'guest' && Utils.Emit(_socket, MessageStore.UpdateField, { id, diff }); } let _UpdateField: (id: string, diff: any) => void = errorFunc; @@ -533,11 +553,11 @@ export namespace DocServer { } export function DeleteDocument(id: string) { - Utils.Emit(_socket, MessageStore.DeleteField, id); + Doc.CurrentUserEmail !== 'guest' && Utils.Emit(_socket, MessageStore.DeleteField, id); } export function DeleteDocuments(ids: string[]) { - Utils.Emit(_socket, MessageStore.DeleteFields, ids); + Doc.CurrentUserEmail !== 'guest' && Utils.Emit(_socket, MessageStore.DeleteFields, ids); } function _respondToDeleteImpl(ids: string | string[]) { |