diff options
-rw-r--r-- | src/fields/List.ts | 8 | ||||
-rw-r--r-- | src/fields/util.ts | 3 | ||||
-rw-r--r-- | src/server/websocket.ts | 62 |
3 files changed, 68 insertions, 5 deletions
diff --git a/src/fields/List.ts b/src/fields/List.ts index 9c7794813..eb735dec2 100644 --- a/src/fields/List.ts +++ b/src/fields/List.ts @@ -77,10 +77,16 @@ const listHandlers: any = { item[OnUpdate] = updateFunction(list, i + start, item, this); } } + let hintArray: {val : any, index : number}[] = []; + for(let i = start; i < start + deleteCount; i++) { + hintArray.push({val : list.__fields[i], index : i}); + } const res = list.__fields.splice(start, deleteCount, ...items); + // console.log(hintArray); + // console.log(list.__fields); this[Update]( items.length === 0 && deleteCount - ? { op: '$remFromSet', items: removed, length: list.__fields.length } + ? { op: '$remFromSet', items: removed, hint : { start : start, deleteCount : deleteCount, hintArray : hintArray}, length: list.__fields.length } : items.length && !deleteCount && start === list.__fields.length ? { op: '$addToSet', items, length: list.__fields.length } : undefined diff --git a/src/fields/util.ts b/src/fields/util.ts index 92f3a69eb..254b70fa7 100644 --- a/src/fields/util.ts +++ b/src/fields/util.ts @@ -37,6 +37,7 @@ import { RichTextField } from './RichTextField'; import { SchemaHeaderField } from './SchemaHeaderField'; import { ComputedField } from './ScriptField'; import { ScriptCast, StrCast } from './Types'; +import { blue } from 'colors'; function _readOnlySetter(): never { throw new Error("Documents can't be modified in read-only mode"); @@ -377,7 +378,7 @@ export function updateFunction(target: any, prop: any, value: any, receiver: any diff?.op === '$addToSet' ? { $addToSet: { ['fields.' + prop]: SerializationHelper.Serialize(new List<Doc>(diff.items)) } } : diff?.op === '$remFromSet' - ? { $remFromSet: { ['fields.' + prop]: SerializationHelper.Serialize(new List<Doc>(diff.items)) } } + ? { $remFromSet: { ['fields.' + prop]: SerializationHelper.Serialize(new List<Doc>(diff.items)), hint : diff.hint } } : { $set: { ['fields.' + prop]: SerializationHelper.Serialize(value) } }; !op.$set && ((op as any).length = diff.length); const prevValue = ObjectField.MakeCopy(lastValue as List<any>); diff --git a/src/server/websocket.ts b/src/server/websocket.ts index 2acdaa5a3..74b5dacaa 100644 --- a/src/server/websocket.ts +++ b/src/server/websocket.ts @@ -317,21 +317,77 @@ export namespace WebSocket { ); } + function findClosestIndex(list: any, indexesToDelete: number[], value: any, hintIndex : number) { + let closestIndex = -1; + for(let i = 0; i < list.length; i++) { + if(list[i] == value && !indexesToDelete.includes(i)) { + if(Math.abs(i - hintIndex) < Math.abs(closestIndex - hintIndex)) { + closestIndex = i; + } + } + } + return closestIndex; + } + function remFromListField(socket: Socket, diff: Diff, curListItems?: Transferable): void { + // console.log("##### %O", diff); diff.diff.$set = diff.diff.$remFromSet; delete diff.diff.$remFromSet; + // console.log(JSON.stringify(diff)); const updatefield = Array.from(Object.keys(diff.diff.$set))[0]; + // console.log("websocket/remfromlist: UPDATE FIELD: " + updatefield); const remListItems = diff.diff.$set[updatefield].fields; const curList = (curListItems as any)?.fields?.[updatefield.replace('fields.', '')]?.fields.filter((f: any) => f !== null) || []; - diff.diff.$set[updatefield].fields = curList?.filter( - (curItem: any) => !remListItems.some((remItem: any) => (remItem.fieldId ? remItem.fieldId === curItem.fieldId : remItem.heading ? remItem.heading === curItem.heading : remItem === curItem)) - ); + const hint = diff.diff.$set.hint; + // console.log(remListItems); + // console.log(curList); + + + if(hint) { + // console.log("websocket/remfromlist: %O", hint); + // console.log(findClosestIndex([5, 5, 3], [], 5, 0)); + // console.log(findClosestIndex([5, 5, 3], [0], 5, 1)); + let indexesToRemove: number[] = []; + for(let i = 0; i < hint.deleteCount; i++) { + // console.log("VALUE: %d", remListItems[i]); + // console.log("HINT INDEX: %d", i + hint.start); + if(curList[i + hint.start] == remListItems[i]) { + indexesToRemove.push(i + hint.start); + continue; + } + + let closestIndex = findClosestIndex(curList, indexesToRemove, remListItems[i], i + hint.start); + if(closestIndex != -1) { + indexesToRemove.push(closestIndex); + } else { + console.log("Item to delete was not found - index = -1"); + } + } + + // console.log("INDEXES TO REMOVE: ", indexesToRemove); + diff.diff.$set[updatefield].fields = curList?.filter( + (curItem: any, index : number) => !(indexesToRemove.includes(index)) + ); + // console.log("websocket/remfromlist: newdiff: %O", diff.diff.$set[updatefield].fields); + } else { + diff.diff.$set[updatefield].fields = curList?.filter( + (curItem: any) => !remListItems.some((remItem: any) => (remItem.fieldId ? remItem.fieldId === curItem.fieldId : + remItem.heading ? remItem.heading === curItem.heading : remItem === curItem)) + ); + // console.log("websocket/remfromlist: newdiff: %O", diff.diff.$set[updatefield].fields); + } + + const sendBack = diff.diff.length !== diff.diff.$set[updatefield].fields.length; + // console.log("websocket/remfromlist: DIFFY " + JSON.stringify(diff.diff.$set)); + // console.log("websocket/remfromlist: DIFF LENGTH " + diff.diff.length); + // console.log("websocket/remfromlist: DIFF $SET " + diff.diff.$set[updatefield].fields); delete diff.diff.length; Database.Instance.update( diff.id, diff.diff, () => { + // console.log("websocket/remfromlist: lambda: %s", JSON.stringify(diff)) if (sendBack) { console.log('SEND BACK'); const id = socket.id; |