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