11import  {  fromCollectionRef  }  from  '../observable/fromRef' ; 
22import  {  Observable ,  SchedulerLike  }  from  'rxjs' ; 
3- import  {  map ,  scan  }  from  'rxjs/operators' ; 
3+ import  {  distinctUntilChanged ,   map ,  pairwise ,   scan ,   startWith  }  from  'rxjs/operators' ; 
44
55import  {  DocumentChange ,  DocumentChangeAction ,  DocumentChangeType ,  Query  }  from  '../interfaces' ; 
66
@@ -25,8 +25,29 @@ export function sortedChanges<T>(
2525  scheduler ?: SchedulerLike ) : Observable < DocumentChangeAction < T > [ ] >  { 
2626  return  fromCollectionRef ( query ,  scheduler ) 
2727    . pipe ( 
28-       map ( changes  =>  changes . payload . docChanges ( ) ) , 
29-       scan ( ( current ,  changes )  =>  combineChanges ( current ,  changes ,  events ) ,  [ ] ) , 
28+       startWith ( undefined ) , 
29+       pairwise ( ) , 
30+       scan ( ( current ,  [ priorChanges ,  changes ] )  =>  { 
31+         const  docChanges  =  changes . payload . docChanges ( ) ; 
32+         const  ret  =  combineChanges ( current ,  docChanges ,  events ) ; 
33+         // docChanges({ includeMetadataChanges: true }) does't include metadata changes... wat? 
34+         if  ( events . indexOf ( 'modified' )  >  - 1  &&  priorChanges  && 
35+             JSON . stringify ( priorChanges . payload . metadata )  !==  JSON . stringify ( changes . payload . metadata ) )  { 
36+           return  ret . map ( it  =>  { 
37+             const  partOfDocChanges  =  ! ! docChanges . find ( d  =>  d . doc . ref . isEqual ( it . doc . ref ) ) ; 
38+             return  { 
39+               // if it's not one of the changed docs that means we already saw it's order change 
40+               // so this is purely metadata, so don't move the doc 
41+               oldIndex : partOfDocChanges  ? it . oldIndex  : it . newIndex , 
42+               newIndex : it . newIndex , 
43+               type : 'modified' , 
44+               doc : changes . payload . docs . find ( d  =>  d . ref . isEqual ( it . doc . ref ) ) 
45+             } ; 
46+           } ) ; 
47+         } 
48+         return  ret ; 
49+       } ,  [ ] ) , 
50+       distinctUntilChanged ( ) ,  // cut down on unneed change cycles 
3051      map ( changes  =>  changes . map ( c  =>  ( {  type : c . type ,  payload : c  }  as  DocumentChangeAction < T > ) ) ) ) ; 
3152} 
3253
@@ -44,6 +65,21 @@ export function combineChanges<T>(current: DocumentChange<T>[], changes: Documen
4465  return  current ; 
4566} 
4667
68+ /** 
69+  * Splice arguments on top of a sliced array, to break top-level === 
70+  * this is useful for change-detection 
71+  */ 
72+ function  sliceAndSplice < T > ( 
73+   original : T [ ] , 
74+   start : number , 
75+   deleteCount : number , 
76+   ...args : T [ ] 
77+ ) : T [ ]  { 
78+   const  returnArray  =  original . slice ( ) ; 
79+   returnArray . splice ( start ,  deleteCount ,  ...args ) ; 
80+   return  returnArray ; 
81+ } 
82+ 
4783/** 
4884 * Creates a new sorted array from a new change. 
4985 */ 
@@ -53,24 +89,26 @@ export function combineChange<T>(combined: DocumentChange<T>[], change: Document
5389      if  ( combined [ change . newIndex ]  &&  combined [ change . newIndex ] . doc . ref . isEqual ( change . doc . ref ) )  { 
5490        // Not sure why the duplicates are getting fired 
5591      }  else  { 
56-         combined . splice ( change . newIndex ,  0 ,  change ) ; 
92+         return   sliceAndSplice ( combined ,   change . newIndex ,  0 ,  change ) ; 
5793      } 
5894      break ; 
5995    case  'modified' :
6096      if  ( combined [ change . oldIndex ]  ==  null  ||  combined [ change . oldIndex ] . doc . ref . isEqual ( change . doc . ref ) )  { 
6197        // When an item changes position we first remove it 
6298        // and then add it's new position 
6399        if  ( change . oldIndex  !==  change . newIndex )  { 
64-           combined . splice ( change . oldIndex ,  1 ) ; 
65-           combined . splice ( change . newIndex ,  0 ,  change ) ; 
100+           const  copiedArray  =  combined . slice ( ) ; 
101+           copiedArray . splice ( change . oldIndex ,  1 ) ; 
102+           copiedArray . splice ( change . newIndex ,  0 ,  change ) ; 
103+           return  copiedArray ; 
66104        }  else  { 
67-           combined . splice ( change . newIndex ,  1 ,  change ) ; 
105+           return   sliceAndSplice ( combined ,   change . newIndex ,  1 ,  change ) ; 
68106        } 
69107      } 
70108      break ; 
71109    case  'removed' :
72110      if  ( combined [ change . oldIndex ]  &&  combined [ change . oldIndex ] . doc . ref . isEqual ( change . doc . ref ) )  { 
73-         combined . splice ( change . oldIndex ,  1 ) ; 
111+         return   sliceAndSplice ( combined ,   change . oldIndex ,  1 ) ; 
74112      } 
75113      break ; 
76114  } 
0 commit comments