package Ġorg . re kotlin router Ċ Ċ import Ġandroid . os . Handler Ċ import Ġandroid . os . Looper Ċ import Ġorg . re kotlin . State Type Ċ import Ġorg . re kotlin . Store Type Ċ import Ġorg . re kotlin . Store Subscriber Ċ import Ġorg . re kotlin . Subscription Ċ Ċ // Ġinternal Ġmodel Ċ Ċ internal Ġsealed Ġclass ĠRouting Action Ċ Ċ internal Ġdata Ġclass ĠPush ( ĊĠĠĠĠĠĠĠ Ġval Ġro utable Index : ĠInt , ĊĠĠĠĠĠĠĠ Ġval Ġsegment To Push : ĠRoute Segment Ċ ) Ġ: ĠRouting Action () Ċ Ċ internal Ġdata Ġclass ĠPop ( ĊĠĠĠĠĠĠĠ Ġval Ġro utable Index : ĠInt , ĊĠĠĠĠĠĠĠ Ġval Ġsegment To Pop : ĠRoute Segment Ċ ) Ġ: ĠRouting Action () Ċ Ċ internal Ġdata Ġclass ĠChange ( ĊĠĠĠĠĠĠĠ Ġval Ġro utable Index : ĠInt , ĊĠĠĠĠĠĠĠ Ġval Ġsegment Te Replace : ĠRoute Segment , ĊĠĠĠĠĠĠĠ Ġval Ġnew Segment : ĠRoute Segment Ċ ) Ġ: ĠRouting Action () Ċ Ċ // Ġpublic Ġrouter Ċ Ċ class ĠRouter < router State Type Ġ: ĠState Type >( ĊĠĠĠĠĠĠĠ Ġvar Ġstore : ĠStore Type < router State Type >, ĊĠĠĠĠĠĠĠ Ġroot Rout able : ĠRout able , ĊĠĠĠĠĠĠĠ Ġstate Transform : Ġ( Subscription < router State Type >) Ġ-> ĠSubscription < Navigation State >, ĊĠĠĠĠĠĠĠ Ġprivate Ġval Ġmain Thread Handler : ĠHandler Ġ= ĠHandler ( Looper . get Main Looper ()) Ġ// Ġfor Ġtesting Ċ ) Ġ: ĠStore Subscriber < Navigation State > Ġ{ ĊĊĠĠĠ Ġprivate Ġvar Ġprevious Route : ĠRoute Ġ= ĠRoute () ĊĊĠĠĠ Ġ// ĠTODO : ĠCollections . synchronized List Ġvs ĠCopy On Write ArrayList ĊĠĠĠ Ġ// Ġvar Ġrout ables : ĠList < Rout able > Ġ= ĠCollections . synchronized List ( array ListOf < Rout able >()) ĊĠĠĠ Ġprivate Ġval Ġrout ables : ĠMutable List < Rout able > Ġ= Ġmutable ListOf () ĊĊĠĠĠ Ġinit Ġ{ ĊĠĠĠĠĠĠĠ Ġthis . rout ables . add ( root Rout able ) ĊĠĠĠĠĠĠĠ Ġthis . store . subscribe ( this , Ġstate Transform ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġoverride Ġfun ĠnewState ( state : ĠNavigation State ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrouting Actions Ġ= Ġrouting Actions For Transition From ( previous Route , Ġstate . route ) ĊĠĠĠĠĠĠĠ Ġif Ġ( routing Actions . isNotEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrouting Actions . forEach Ġ{ Ġrouting Action Ġ-> ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrouting Serial Action Handler ( routing Action , Ġstate ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġprevious Route Ġ= Ġstate . route Ġ// Ġdo Ġwe Ġneed Ġa Ġdeep Ġcopy ? ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġrouting Serial Action Handler ( action : ĠRouting Action , Ġstate : ĠNavigation State ) Ġ{ ĊĠĠĠĠĠĠĠ Ġsynchronized ( lock Ġ= Ġrout ables ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġwhen Ġ( action ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠPop Ġ-> Ġmain Thread Handler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrout ables [ action . ro utable Index ]. pop Route Segment ( action . segment To Pop , Ġstate . animated ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrout ables . remove At ( action . ro utable Index Ġ+ Ġ 1 ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠPush Ġ-> Ġmain Thread Handler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnew Rout able Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrout ables [ action . ro utable Index ]. push Route Segment ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġaction . segment To Push , Ġstate . animated ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrout ables . add ( new Rout able ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġis ĠChange Ġ-> Ġmain Thread Handler . post Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrout ables [ action . ro utable Index Ġ+ Ġ 1 ] Ġ= ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġrout ables [ action . ro utable Index ]. change Route Segment ( ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġfrom Ġ= Ġaction . segment Te Replace , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġto Ġ= Ġaction . new Segment , ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġanimated Ġ= Ġstate . animated ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} Ċ } Ċ Ċ // ĠRoute ĠTransformation ĠLogic Ċ Ċ private Ġfun Ġlargest Common Sub route ( old Route : ĠRoute , Ġnew Route : ĠRoute ): ĠInt Ġ{ ĊĠĠĠ Ġvar Ġlargest Common Sub route Ġ= Ġ- 1 ĊĊĠĠĠ Ġwhile Ġ( largest Common Sub route Ġ+ Ġ 1 Ġ< Ġnew Route . count Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlargest Common Sub route Ġ+ Ġ 1 Ġ< Ġold Route . count Ġ&& ĊĠĠĠĠĠĠĠĠĠĠĠ Ġnew Route [ largest Common Sub route Ġ+ Ġ 1 ] Ġ== Ġold Route [ largest Common Sub route Ġ+ Ġ 1 ]) Ġ{ ĊĠĠĠĠĠĠĠ Ġlargest Common Sub route Ġ+= Ġ 1 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġlargest Common Sub route Ċ } ĊĊ Ċ // ĠMaps ĠRoute Ġindex Ġto ĠRout able Ġindex . ĠRout able Ġindex Ġis Ġoffset Ġby Ġ 1 Ġbecause Ġthe Ġroot ĠRout able Ċ // Ġis Ġnot Ġrepresented Ġin Ġthe Ġroute , Ġe . g . Ċ // Ġroute Ġ= Ġ[" tab Bar "] Ċ // Ġrout ables Ġ= Ġ[ Root Rout able , ĠTab Bar Rout able ] Ċ private Ġfun Ġro utable Index For Route Segment ( segment : ĠInt ) Ġ= Ġsegment Ġ+ Ġ 1 Ċ Ċ internal Ġfun Ġrouting Actions For Transition From ( old Route : ĠRoute , Ġnew Route : ĠRoute ): ĠList < Routing Action > Ġ{ ĊĊĠĠĠ Ġval Ġrouting Actions Ġ= Ġarray ListOf < Routing Action >() ĊĊĠĠĠ Ġ// ĠFind Ġthe Ġlast Ġcommon Ġsub route Ġbetween Ġtwo Ġroutes ĊĠĠĠ Ġval Ġcommon Sub route Ġ= Ġlargest Common Sub route ( old Route , Ġnew Route ) ĊĊĠĠĠ Ġif Ġ( common Sub route Ġ== Ġold Route . count Ġ- Ġ 1 Ġ&& Ġcommon Sub route Ġ== Ġnew Route . count Ġ- Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġreturn Ġarray ListOf () ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠKeep s Ġtrack Ġwhich Ġelement Ġof Ġthe Ġroutes Ġwe Ġare Ġworking Ġon ĊĠĠĠ Ġ// ĠWe Ġstart Ġat Ġthe Ġend Ġof Ġthe Ġold Ġroute ĊĠĠĠ Ġvar Ġroute Building Index Ġ= Ġold Route . count Ġ- Ġ 1 ĊĊĠĠĠ Ġ// ĠPop Ġall Ġroute Ġsegments Ġof Ġthe Ġold Ġroute Ġthat Ġare Ġno Ġlonger Ġin Ġthe Ġnew Ġroute ĊĠĠĠ Ġ// ĠStop Ġone Ġelement Ġahead Ġof Ġthe Ġcommon Sub route . ĠWhen Ġwe Ġare Ġone Ġelement Ġahead Ġof Ġthe ĊĠĠĠ Ġ// Ġcomm mon Ġsub route Ġwe Ġhave Ġthree Ġoptions : ĊĠĠĠ Ġ// ĊĠĠĠ Ġ// Ġ 1 . ĠThe Ġold Ġroute Ġhad Ġan Ġelement Ġafter Ġthe Ġcommon Sub route Ġand Ġthe Ġnew Ġroute Ġdoes Ġnot ĊĠĠĠ Ġ// ĠĠĠ Ġwe Ġneed Ġto Ġpop Ġthe Ġroute Ġsegment Ġafter Ġthe Ġcommon Sub route ĊĠĠĠ Ġ// Ġ 2 . ĠThe Ġold Ġroute Ġhad Ġno Ġelement Ġafter Ġthe Ġcommon Sub route Ġand Ġthe Ġnew Ġroute Ġdoes , Ġwe ĊĠĠĠ Ġ// ĠĠĠ Ġwe Ġneed Ġto Ġpush Ġthe Ġroute Ġsegment ( s ) Ġafter Ġthe Ġcommon Sub route ĊĠĠĠ Ġ// Ġ 3 . ĠThe Ġnew Ġroute Ġhas Ġa Ġdifferent Ġelement Ġafter Ġthe Ġcommon Sub route , Ġwe Ġneed Ġto Ġreplace ĊĠĠĠ Ġ// ĠĠĠ Ġthe Ġold Ġroute Ġelement Ġwith Ġthe Ġnew Ġone ĊĠĠĠ Ġwhile Ġ( route Building Index Ġ> Ġcommon Sub route Ġ+ Ġ 1 ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġroute Segment To Pop Ġ= Ġold Route [ route Building Index ] ĊĊĠĠĠĠĠĠĠ Ġval Ġpop Action Ġ= ĠPop ( ro utable Index For Route Segment ( route Building Index Ġ- Ġ 1 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġroute Segment To Pop ) ĊĠĠĠĠĠĠĠ Ġrouting Actions . add ( pop Action ) ĊĠĠĠĠĠĠĠ Ġroute Building Index Ġ-= Ġ 1 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠThis Ġis Ġthe Ġ 3 . Ġcase : ĊĠĠĠ Ġ// Ġ" The Ġnew Ġroute Ġhas Ġa Ġdifferent Ġelement Ġafter Ġthe Ġcommon Sub route , Ġwe Ġneed Ġto Ġreplace ĊĠĠĠ Ġ// Ġ Ġthe Ġold Ġroute Ġelement Ġwith Ġthe Ġnew Ġone " ĊĠĠĠ Ġif Ġ(( old Route . count Ġ> Ġ( common Sub route Ġ+ Ġ 1 )) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ&& Ġ( new Route . count Ġ> Ġ( common Sub route Ġ+ Ġ 1 ))) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġchange Action Ġ= ĠChange ( ro utable Index For Route Segment ( common Sub route ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġold Route [ common Sub route Ġ+ Ġ 1 ], ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġnew Route [ common Sub route Ġ+ Ġ 1 ]) ĊĊĠĠĠĠĠĠĠ Ġrouting Actions . add ( change Action ) ĊĠĠĠ Ġ} ĊĠĠĠ Ġ// ĠThis Ġis Ġthe Ġ 1 . Ġcase : ĊĠĠĠ Ġ// Ġ" The Ġold Ġroute Ġhad Ġan Ġelement Ġafter Ġthe Ġcommon Sub route Ġand Ġthe Ġnew Ġroute Ġdoes Ġnot ĊĠĠĠ Ġ// Ġ Ġwe Ġneed Ġto Ġpop Ġthe Ġroute Ġsegment Ġafter Ġthe Ġcommon Sub route " ĊĠĠĠ Ġelse Ġif Ġ( old Route . count Ġ> Ġnew Route . count ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġpop Action Ġ= ĠPop ( ro utable Index For Route Segment ( route Building Index Ġ- Ġ 1 ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġold Route [ route Building Index ]) ĊĊĠĠĠĠĠĠĠ Ġ// routing Actions Ġ= Ġrouting Actions . plus ( pop Action ) ĊĠĠĠĠĠĠĠ Ġrouting Actions . add ( pop Action ) ĊĠĠĠĠĠĠĠ Ġroute Building Index Ġ-= Ġ 1 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ// ĠPush Ġremainder Ġof Ġelements Ġin Ġnew ĠRoute Ġthat Ġweren 't Ġin Ġold ĠRoute , Ġthis Ġcovers ĊĠĠĠ Ġ// Ġthe Ġ 2 . Ġcase : ĊĠĠĠ Ġ// Ġ" The Ġold Ġroute Ġhad Ġno Ġelement Ġafter Ġthe Ġcommon Sub route Ġand Ġthe Ġnew Ġroute Ġdoes , ĊĠĠĠ Ġ// Ġ Ġwe Ġneed Ġto Ġpush Ġthe Ġroute Ġsegment ( s ) Ġafter Ġthe Ġcommon Sub route " ĊĠĠĠ Ġval Ġnew Route Index Ġ= Ġnew Route . count Ġ- Ġ 1 ĊĊĠĠĠ Ġwhile Ġ( route Building Index Ġ< Ġnew Route Index ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġroute Segment To Push Ġ= Ġnew Route [ route Building Index Ġ+ Ġ 1 ] ĊĊĠĠĠĠĠĠĠ Ġval Ġpush Action Ġ= ĠPush ( ro utable Index For Route Segment ( route Building Index ), ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġroute Segment To Push ) ĊĊĠĠĠĠĠĠĠ Ġrouting Actions . add ( push Action ) ĊĠĠĠĠĠĠĠ Ġroute Building Index Ġ+= Ġ 1 ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġreturn Ġrouting Actions Ċ } Ċ