11import Dexie from 'dexie' ;
2+ import sortBy from 'lodash/sortBy' ;
23import db from 'shared/data/db' ;
34import { promiseChunk } from 'shared/utils/helpers' ;
4- import { CHANGES_TABLE , CHANGE_TYPES , IGNORED_SOURCE } from 'shared/data/constants' ;
5- import { Session } from 'shared/data/resources' ;
5+ import {
6+ CHANGES_TABLE ,
7+ CHANGE_TYPES ,
8+ IGNORED_SOURCE ,
9+ RELATIVE_TREE_POSITIONS ,
10+ } from 'shared/data/constants' ;
611import { INDEXEDDB_RESOURCES } from 'shared/data/registry' ;
712
813/**
@@ -61,15 +66,9 @@ export class ChangeTracker {
6166 }
6267
6368 // Grab the most recent change in the changes table, if it exists, which it might not
64- // if everything has been synced and applied, otherwise check the session for its max rev
65- const [ mostRecentChange , session ] = await Promise . all ( [
66- db [ CHANGES_TABLE ] . orderBy ( 'rev' ) . last ( ) ,
67- Session . getSession ( ) ,
68- ] ) ;
69-
70- this . _startingRev = mostRecentChange
71- ? mostRecentChange . rev
72- : session . max_rev [ Session . currentChannelId ] ;
69+ const mostRecentChange = await db [ CHANGES_TABLE ] . orderBy ( 'rev' ) . last ( ) ;
70+
71+ this . _startingRev = mostRecentChange ? mostRecentChange . rev : null ;
7372 }
7473
7574 /**
@@ -78,10 +77,16 @@ export class ChangeTracker {
7877 */
7978 async stop ( ) {
8079 // Collect the changes
81- const changes = db [ CHANGES_TABLE ] . where ( 'rev' )
82- . above ( this . _startingRev )
83- . filter ( change => ! change . source . match ( IGNORED_SOURCE ) ) ;
84- this . _changes = await changes . sortBy ( 'rev' ) ;
80+ let changes = db [ CHANGES_TABLE ] ;
81+
82+ // If we had a starting rev, filter to only those changes added since
83+ if ( this . _startingRev ) {
84+ changes = changes . where ( 'rev' ) . above ( this . _startingRev ) ;
85+ }
86+
87+ this . _changes = await changes
88+ . filter ( change => ! change . source . match ( IGNORED_SOURCE ) )
89+ . sortBy ( 'rev' ) ;
8590 }
8691
8792 /**
@@ -131,7 +136,7 @@ export class ChangeTracker {
131136 }
132137 return Promise . resolve ( ) ;
133138 }
134- return resource . transaction ( { } , ( ) => {
139+ return resource . transaction ( { } , CHANGES_TABLE , ( ) => {
135140 // If we had created something, we'll delete it
136141 // Special MOVED case here comes from the operation of COPY then MOVE for duplicating
137142 // content nodes, which in this case would be on the Tree table, so we're removing
@@ -151,9 +156,21 @@ export class ChangeTracker {
151156 // If we updated or deleted it, we just want the old stuff back
152157 return resource . table . put ( change . oldObj ) ;
153158 } else if ( change . type === CHANGE_TYPES . MOVED && change . oldObj ) {
154- // Lastly if this is a MOVE, then this was likely a single operation, so we just roll
155- // it back
156- return resource . table . put ( change . oldObj ) ;
159+ // Lastly if this is a MOVE, we generate a reverse move back to its old position
160+ const { parent, lft } = change . oldObj ;
161+
162+ // Collect the affected node's siblings prior to the change
163+ return resource . where ( { parent } , false ) . then ( siblings => {
164+ // Search the siblings ordered by `lft` to find the first a sibling
165+ // where we should move the node, positioned before that sibling
166+ let relativeSibling = sortBy ( siblings , 'lft' ) . find ( sibling => sibling . lft >= lft ) ;
167+ if ( relativeSibling ) {
168+ return resource . move ( change . key , relativeSibling . id , RELATIVE_TREE_POSITIONS . LEFT ) ;
169+ }
170+
171+ // this handles if there were no siblings OR if the deleted node was at the end
172+ return resource . move ( change . key , parent , RELATIVE_TREE_POSITIONS . LAST_CHILD ) ;
173+ } ) ;
157174 } else {
158175 if ( process . env . NODE_ENV !== 'production' ) {
159176 /* eslint-disable no-console */
0 commit comments