diff --git a/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js b/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js index fc40cc720..d17e2ffcd 100644 --- a/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js +++ b/Libraries/CustomComponents/Navigator/Navigation/NavigationRouteStack.js @@ -11,7 +11,7 @@ var invariant = require('invariant'); type IterationCallback = (route: any, index: number, key: string) => void; -var {List} = immutable; +var {List, Set} = immutable; function isRouteEmpty(route: any): boolean { return (route === undefined || route === null || route === '') || false; @@ -32,6 +32,12 @@ class RouteNode { } } +var StackDiffRecord = immutable.Record({ + key: null, + route: null, + index: null, +}); + /** * The immutable route stack. */ @@ -201,6 +207,25 @@ class RouteStack { } } + /** + * Returns a Set excluding any routes contained within the stack given. + */ + subtract(stack: RouteStack): Set { + var items = []; + this._routeNodes.forEach((node: RouteNode, index: number) => { + if (!stack._routeNodes.contains(node)) { + items.push( + new StackDiffRecord({ + route: node.value, + index: index, + key: node.key, + }) + ); + } + }); + return new Set(items); + } + _update(index: number, routeNodes: List): RouteStack { if (this._index === index && this._routeNodes === routeNodes) { return this; diff --git a/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js b/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js index df75c04ef..77ce34c75 100644 --- a/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js +++ b/Libraries/CustomComponents/Navigator/Navigation/__tests__/NavigationRouteStack-test.js @@ -31,6 +31,10 @@ jest var NavigationRouteStack = require('NavigationRouteStack'); +function assetStringNotEmpty(str) { + expect(!!str && typeof str === 'string').toBe(true); +} + describe('NavigationRouteStack:', () => { // Different types of routes. var ROUTES = [ @@ -341,4 +345,62 @@ describe('NavigationRouteStack:', () => { ['b', 1, true], ]); }); + + // Diff + it('subtracts stack', () => { + var stack1 = new NavigationRouteStack(2, ['a', 'b', 'c']); + var stack2 = stack1.pop().pop().push('x').push('y'); + + var diff = stack1.subtract(stack2); + + var result = diff.toJS().map((record) => { + assetStringNotEmpty(record.key); + return { + index: record.index, + route: record.route, + }; + }); + + // route `b` and `c` are no longer in the stack. + expect(result).toEqual([ + { + index: 1, + route: 'b', + }, + { + index: 2, + route: 'c', + }, + ]); + }); + + it('only subtracts the derived stack', () => { + var stack1 = new NavigationRouteStack(2, ['a', 'b', 'c']); + var stack2 = new NavigationRouteStack(0, ['a']); + var diff = stack1.subtract(stack2); + + var result = diff.toJS().map((record) => { + assetStringNotEmpty(record.key); + return { + index: record.index, + route: record.route, + }; + }); + + expect(result).toEqual([ + { + index: 0, + route: 'a', + }, + { + index: 1, + route: 'b', + }, + { + index: 2, + route: 'c', + }, + ]); + + }); });