@coolon/angular-ui-powerups 0.0.115 → 0.0.117

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -16,6 +16,7 @@ export class NavigationState extends GarbageCollector {
16
16
  super();
17
17
  this.context = context;
18
18
  this._visits = new Map();
19
+ this.debugPropertyKeys = [];
19
20
  }
20
21
  /**
21
22
  * @return {?}
@@ -152,14 +153,18 @@ export class NavigationState extends GarbageCollector {
152
153
  createTransitionStateFor(event) {
153
154
  /** @type {?} */
154
155
  const popstate = event.navigationTrigger === 'popstate';
155
- return popstate ?
156
- this.interactionService.isActive() ?
157
- new NavigationState.InteractionPopStateTransition(this.context, this.currentRouterUrl()) :
158
- new NavigationState.PopStateTransition(this.context, this.currentRouterUrl())
159
- :
160
- this.interactionService.isActive() ?
161
- new NavigationState.InteractionTransition(this.context, this.currentRouterUrl()) :
162
- new NavigationState.NavigationTransition(this.context, this.currentRouterUrl());
156
+ /** @type {?} */
157
+ const inInteraction = this.interactionService.isActive();
158
+ if (popstate) {
159
+ return inInteraction ?
160
+ new NavigationState.LeavingInteractionAfterPopStateTransition(this.context, this.currentRouterUrl(), event.url) :
161
+ new NavigationState.PopStateTransition(this.context, this.currentRouterUrl(), event.url);
162
+ }
163
+ else {
164
+ return inInteraction ?
165
+ new NavigationState.StartingInteractionTransition(this.context, this.currentRouterUrl()) :
166
+ new NavigationState.NavigationTransition(this.context, this.currentRouterUrl());
167
+ }
163
168
  }
164
169
  /**
165
170
  * @protected
@@ -170,6 +175,7 @@ export class NavigationState extends GarbageCollector {
170
175
  new NavigationState.IdleDuringInteraction(this.context, this.currentRouterUrl()) :
171
176
  new NavigationState.Idle(this.context);
172
177
  }
178
+ //
173
179
  /**
174
180
  * @param {?} url
175
181
  * @return {?}
@@ -177,11 +183,35 @@ export class NavigationState extends GarbageCollector {
177
183
  resetBrowserLocation(url) {
178
184
  this.placeRouter.resetBrowserLocation(url);
179
185
  }
186
+ /**
187
+ * @param {?} event
188
+ * @param {?=} reason
189
+ * @return {?}
190
+ */
191
+ ignore(event, reason) {
192
+ reason = reason ? ` -> ${reason}` : '';
193
+ Logger.get(this).info(`Ignoring router event${reason}: ${event.constructor.name} -> ${event.url} :: ${this.toString()}`);
194
+ return this;
195
+ }
180
196
  /**
181
197
  * @return {?}
182
198
  */
183
199
  toString() {
184
- return this.constructor.name;
200
+ return `${this.constructor.name}(${this.debugState()})`;
201
+ }
202
+ /**
203
+ * @protected
204
+ * @param {?=} properties
205
+ * @return {?}
206
+ */
207
+ debugState(properties) {
208
+ return (properties || this.debugPropertyKeys).map((/**
209
+ * @param {?} p
210
+ * @return {?}
211
+ */
212
+ p => {
213
+ return `${p}: ${this[p]}`;
214
+ })).join(', ');
185
215
  }
186
216
  }
187
217
  if (false) {
@@ -196,6 +226,8 @@ if (false) {
196
226
  NavigationState.prototype.startingUrl;
197
227
  /** @type {?} */
198
228
  NavigationState.prototype.isPopState;
229
+ /** @type {?} */
230
+ NavigationState.prototype.debugPropertyKeys;
199
231
  /**
200
232
  * @type {?}
201
233
  * @protected
@@ -257,7 +289,7 @@ if (false) {
257
289
  }
258
290
  if (this.placeRouter.hasActiveInteractionIds(event.url)) {
259
291
  Logger.get(this).info(`navigation started with interaction outlet -> ${event.url}`);
260
- return new InteractionTransition(this.context, event.url);
292
+ return new StartingInteractionTransition(this.context, event.url);
261
293
  }
262
294
  else {
263
295
  return this.createTransitionStateFor(event);
@@ -332,10 +364,10 @@ if (false) {
332
364
  return new Idle(this.context);
333
365
  }
334
366
  /**
335
- * @param {?} locationTriggerUrl
367
+ * @param {?} newUrl
336
368
  * @return {?}
337
369
  */
338
- onBackClickedDuringNavigationInteraction(locationTriggerUrl) {
370
+ onBackClickedDuringNavigationInteraction(newUrl) {
339
371
  Logger.get(this).info(`back button pressed during navigation session interaction promise`);
340
372
  // detach the interaction from the session so it doesn't get disposed until the activity has completed.
341
373
  /** @type {?} */
@@ -343,15 +375,15 @@ if (false) {
343
375
  const { when } = Dsl.disposeWith(navigationInteraction);
344
376
  // TODO: I need to make the exclusive interaction context disallow nested activities or
345
377
  // that would mess things up entirely. Or, can I do a context.abortAll().then(..)
378
+ Logger.get(this).info('cancelling current navigation activity..');
346
379
  navigationInteraction.cancelActiveActivity().then((/**
347
380
  * @return {?}
348
381
  */
349
382
  () => {
350
383
  navigationInteraction.dispose();
351
384
  }));
352
- return new CancelledDuringNavigationInteraction(this.context, this.startingUrl, this.isPopState, locationTriggerUrl);
385
+ return this.createNavigationInteractionCancelledState(newUrl);
353
386
  }
354
- // @Trace()
355
387
  /**
356
388
  * @param {?} component
357
389
  * @param {?} currentUrl
@@ -373,7 +405,7 @@ if (false) {
373
405
  });
374
406
  }
375
407
  /**
376
- * @private
408
+ * @protected
377
409
  * @return {?}
378
410
  */
379
411
  detachInteractionContext() {
@@ -399,11 +431,18 @@ if (false) {
399
431
  AbstractNavigationTransition.prototype._interactionContext;
400
432
  /** @type {?} */
401
433
  AbstractNavigationTransition.prototype.startingUrl;
434
+ /**
435
+ * @abstract
436
+ * @param {?} newUrl
437
+ * @return {?}
438
+ */
439
+ AbstractNavigationTransition.prototype.createNavigationInteractionCancelledState = function (newUrl) { };
402
440
  }
403
441
  class NavigationTransition extends AbstractNavigationTransition {
404
442
  constructor() {
405
443
  super(...arguments);
406
444
  this.isPopState = false;
445
+ this.debugPropertyKeys = ['startingUrl'];
407
446
  }
408
447
  /**
409
448
  * @param {?} event
@@ -421,21 +460,31 @@ if (false) {
421
460
  return new Idle(this.context);
422
461
  }
423
462
  /**
463
+ * @param {?} newUrl
424
464
  * @return {?}
425
465
  */
426
- toString() {
427
- return `${this.constructor.name}(startingUrl: ${this.startingUrl})`;
466
+ createNavigationInteractionCancelledState(newUrl) {
467
+ return new LinkTriggeredNavigationInteractionCancelled(this.context, this.startingUrl, newUrl);
428
468
  }
429
469
  }
430
470
  NavigationState.NavigationTransition = NavigationTransition;
431
471
  if (false) {
432
472
  /** @type {?} */
433
473
  NavigationTransition.prototype.isPopState;
474
+ /** @type {?} */
475
+ NavigationTransition.prototype.debugPropertyKeys;
434
476
  }
435
477
  class PopStateTransition extends AbstractNavigationTransition {
436
- constructor() {
437
- super(...arguments);
478
+ /**
479
+ * @param {?} context
480
+ * @param {?} startingUrl
481
+ * @param {?} poppedHistoryUrl
482
+ */
483
+ constructor(context, startingUrl, poppedHistoryUrl) {
484
+ super(context, startingUrl);
485
+ this.poppedHistoryUrl = poppedHistoryUrl;
438
486
  this.isPopState = true;
487
+ this.debugPropertyKeys = ['startingUrl', 'poppedHistoryUrl'];
439
488
  }
440
489
  /**
441
490
  * @param {?} event
@@ -445,7 +494,8 @@ if (false) {
445
494
  // Angular doesn't preserve the url when a guard cancels the back button.
446
495
  // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
447
496
  Logger.get(this).info('WORK-AROUND: Updating browser location after pop state - see angular issue #13586');
448
- this.resetBrowserLocation(this.startingUrl);
497
+ this.resetBrowserLocation(this.poppedHistoryUrl); // put the popped history item back in.
498
+ this.resetBrowserLocation(this.startingUrl); // and now put our own url back in.
449
499
  return new Idle(this.context);
450
500
  }
451
501
  /**
@@ -458,16 +508,54 @@ if (false) {
458
508
  // Angular doesn't preserve the url when a guard cancels the back button.
459
509
  // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
460
510
  Logger.get(this).info('WORK-AROUND: Updating browser location after pop state - see angular issue #13586');
461
- this.resetBrowserLocation(this.startingUrl);
511
+ this.resetBrowserLocation(this.poppedHistoryUrl); // put the popped history item back in.
512
+ this.resetBrowserLocation(this.startingUrl); // and now put our own url back in.
462
513
  }
463
514
  return new Idle(this.context);
464
515
  }
516
+ /**
517
+ * @param {?} locationTriggerUrl
518
+ * @return {?}
519
+ */
520
+ createNavigationInteractionCancelledState(locationTriggerUrl) {
521
+ return new PopStateTriggeredNavigationInteractionCancelled(this.context, this.startingUrl, locationTriggerUrl, this.poppedHistoryUrl);
522
+ }
465
523
  }
466
524
  NavigationState.PopStateTransition = PopStateTransition;
467
525
  if (false) {
468
526
  /** @type {?} */
469
527
  PopStateTransition.prototype.isPopState;
528
+ /** @type {?} */
529
+ PopStateTransition.prototype.debugPropertyKeys;
530
+ /** @type {?} */
531
+ PopStateTransition.prototype.poppedHistoryUrl;
470
532
  }
533
+ /**
534
+ * @abstract
535
+ */
536
+ class AbstractInteractionTransition extends AbstractNavigationTransition {
537
+ /**
538
+ * @param {?} context
539
+ * @param {?} startingUrl
540
+ */
541
+ constructor(context, startingUrl) {
542
+ super(context, startingUrl);
543
+ this.startingUrl = startingUrl;
544
+ this.isTransitional = true;
545
+ }
546
+ }
547
+ NavigationState.AbstractInteractionTransition = AbstractInteractionTransition;
548
+ if (false) {
549
+ /** @type {?} */
550
+ AbstractInteractionTransition.prototype.isTransitional;
551
+ /** @type {?} */
552
+ AbstractInteractionTransition.prototype.startingUrl;
553
+ }
554
+ // The following states exist to handle all events while any kind of navigation is in progress. That way all other states can
555
+ // happily ignore interaction contexts.
556
+ /**
557
+ * This is the non transitional (i.e. rest) state that is used whenever an interaction context is active.
558
+ */
471
559
  class IdleDuringInteraction extends NavigationState {
472
560
  /**
473
561
  * @param {?} context
@@ -478,6 +566,7 @@ if (false) {
478
566
  this.startingUrl = startingUrl;
479
567
  this.isTransitional = false;
480
568
  this.isPopState = false;
569
+ this.debugPropertyKeys = ['startingUrl'];
481
570
  }
482
571
  /**
483
572
  * @param {?} visit
@@ -485,26 +574,26 @@ if (false) {
485
574
  * @return {?}
486
575
  */
487
576
  onPlaceNavigationStart(visit, initialUrl) {
577
+ // we're in an interaction and the user clicked back
488
578
  /** @type {?} */
489
- const navigationTransition = new InteractionTransition(this.context, initialUrl);
579
+ const navigationTransition = new StartingInteractionTransition(this.context, initialUrl);
490
580
  navigationTransition.storeVisit(visit);
491
581
  return navigationTransition;
492
582
  }
493
- // @Trace()
494
583
  /**
495
584
  * @param {?} event
496
585
  * @return {?}
497
586
  */
498
587
  onRouterStarted(event) {
499
- return new InteractionTransition(this.context, event.url);
588
+ return new StartingInteractionTransition(this.context, event.url);
500
589
  }
501
- // @Trace()
502
590
  /**
503
591
  * @param {?} event
504
592
  * @return {?}
505
593
  */
506
594
  onPopState(event) {
507
- return new InteractionPopStateTransition(this.context, event.url);
595
+ // we're in an interaction and the user clicked back
596
+ return new LeavingInteractionAfterPopStateTransition(this.context, event.url, event.url);
508
597
  }
509
598
  }
510
599
  NavigationState.IdleDuringInteraction = IdleDuringInteraction;
@@ -514,39 +603,21 @@ if (false) {
514
603
  /** @type {?} */
515
604
  IdleDuringInteraction.prototype.isPopState;
516
605
  /** @type {?} */
517
- IdleDuringInteraction.prototype.startingUrl;
518
- }
519
- /**
520
- * @abstract
521
- */
522
- class AbstractInteractionTransition extends AbstractNavigationTransition {
523
- /**
524
- * @param {?} context
525
- * @param {?} startingUrl
526
- */
527
- constructor(context, startingUrl) {
528
- super(context, startingUrl);
529
- this.startingUrl = startingUrl;
530
- this.isTransitional = true;
531
- }
532
- }
533
- NavigationState.AbstractInteractionTransition = AbstractInteractionTransition;
534
- if (false) {
535
- /** @type {?} */
536
- AbstractInteractionTransition.prototype.isTransitional;
606
+ IdleDuringInteraction.prototype.debugPropertyKeys;
537
607
  /** @type {?} */
538
- AbstractInteractionTransition.prototype.startingUrl;
608
+ IdleDuringInteraction.prototype.startingUrl;
539
609
  }
540
610
  /**
541
611
  * This state exists to handle all events while any kind of navigation is in progress. That way all other states can
542
612
  * happily ignore interaction contexts.
613
+ * NOTE: This state is activated when ever an interaction is started. It might be better to split it into
614
+ * different states for different scenarios, e.g. starting model, starting model during route guard etc.
543
615
  */
544
- class InteractionTransition extends AbstractInteractionTransition {
616
+ class StartingInteractionTransition extends AbstractInteractionTransition {
545
617
  constructor() {
546
618
  super(...arguments);
547
619
  this.isPopState = false;
548
620
  }
549
- // @Trace()
550
621
  /**
551
622
  * @param {?} event
552
623
  * @return {?}
@@ -562,7 +633,6 @@ if (false) {
562
633
  return new Idle(this.context);
563
634
  }
564
635
  }
565
- // @Trace()
566
636
  /**
567
637
  * @param {?} event
568
638
  * @return {?}
@@ -571,7 +641,6 @@ if (false) {
571
641
  // navigation was aborted.
572
642
  return new IdleDuringInteraction(this.context, this.startingUrl);
573
643
  }
574
- // @Trace()
575
644
  /**
576
645
  * @param {?} event
577
646
  * @return {?}
@@ -584,22 +653,137 @@ if (false) {
584
653
  return new Idle(this.context);
585
654
  }
586
655
  }
656
+ /**
657
+ * @param {?} locationTriggerUrl
658
+ * @return {?}
659
+ */
660
+ createNavigationInteractionCancelledState(locationTriggerUrl) {
661
+ return new LeavingInteractionTransitionCancelled(this.context, this.startingUrl, locationTriggerUrl);
662
+ }
663
+ }
664
+ NavigationState.StartingInteractionTransition = StartingInteractionTransition;
665
+ if (false) {
666
+ /** @type {?} */
667
+ StartingInteractionTransition.prototype.isPopState;
668
+ }
669
+ /**
670
+ * The sequence of router events are:
671
+ * Error -> url = url of navigation link
672
+ * End
673
+ * onPopState url = current intereaction url sans the query params
674
+ * Cancel url == same as above.
675
+ */
676
+ class LeavingInteractionTransitionCancelled extends NavigationState {
677
+ /**
678
+ * @param {?} context
679
+ * @param {?} startingUrl
680
+ * @param {?} locationChangeTriggerUrl
681
+ */
682
+ constructor(context, startingUrl, locationChangeTriggerUrl) {
683
+ super(context);
684
+ this.startingUrl = startingUrl;
685
+ this.locationChangeTriggerUrl = locationChangeTriggerUrl;
686
+ this.isPopState = false;
687
+ this.firstCancelHandled = false;
688
+ this.popStateHandled = false;
689
+ this.debugPropertyKeys = ['idle', 'startingUrl', 'poppedHistoryUrl', 'locationChangeTriggerUrl', 'popStateEventUrl', 'firstCancelHandled', 'popStateHandled'];
690
+ }
691
+ /**
692
+ * @return {?}
693
+ */
694
+ get isTransitional() {
695
+ return true;
696
+ }
697
+ /**
698
+ * @param {?} event
699
+ * @return {?}
700
+ */
701
+ onRouterStarted(event) {
702
+ return this.ignore(event);
703
+ }
704
+ /**
705
+ * @param {?} event
706
+ * @return {?}
707
+ */
708
+ onRouterCancelled(event) {
709
+ // Angular doesn't preserve the url when a guard cancels the back button.
710
+ // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
711
+ Logger.get(this).info('WORK-AROUND: Updating browser location after pop state - see angular issue #13586');
712
+ if (this.interactionService.isActive()) {
713
+ /** @type {?} */
714
+ const interactionIds = this.interactionService.activeInteractionContextIds.value;
715
+ this.resetBrowserLocation(this.placeRouter.parseUrl(this.startingUrl).updateInteractionIds(interactionIds).url);
716
+ }
717
+ else {
718
+ this.resetBrowserLocation(this.startingUrl); // and now put our own url back in.
719
+ }
720
+ return this.createIdleState();
721
+ }
722
+ /**
723
+ * @param {?} event
724
+ * @return {?}
725
+ */
726
+ onRouterEnd(event) {
727
+ return this.ignore(event);
728
+ }
729
+ /**
730
+ * @param {?} event
731
+ * @return {?}
732
+ */
733
+ onRouterError(event) {
734
+ return this.ignore(event);
735
+ }
736
+ /**
737
+ * @param {?} event
738
+ * @return {?}
739
+ */
740
+ onPopState(event) {
741
+ return this.ignore(event);
742
+ }
743
+ /**
744
+ * @param {?} component
745
+ * @param {?} currentUrl
746
+ * @param {?} nextUrl
747
+ * @return {?}
748
+ */
749
+ canDeactivatePlace(component, currentUrl, nextUrl) {
750
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
751
+ return false;
752
+ });
753
+ }
587
754
  }
588
- NavigationState.InteractionTransition = InteractionTransition;
755
+ NavigationState.LeavingInteractionTransitionCancelled = LeavingInteractionTransitionCancelled;
589
756
  if (false) {
590
757
  /** @type {?} */
591
- InteractionTransition.prototype.isPopState;
758
+ LeavingInteractionTransitionCancelled.prototype.isPopState;
759
+ /** @type {?} */
760
+ LeavingInteractionTransitionCancelled.prototype.firstCancelHandled;
761
+ /** @type {?} */
762
+ LeavingInteractionTransitionCancelled.prototype.popStateHandled;
763
+ /** @type {?} */
764
+ LeavingInteractionTransitionCancelled.prototype.popStateEventUrl;
765
+ /** @type {?} */
766
+ LeavingInteractionTransitionCancelled.prototype.debugPropertyKeys;
767
+ /** @type {?} */
768
+ LeavingInteractionTransitionCancelled.prototype.startingUrl;
769
+ /** @type {?} */
770
+ LeavingInteractionTransitionCancelled.prototype.locationChangeTriggerUrl;
592
771
  }
593
772
  /**
594
773
  * This state exists to handle all events while any kind of navigation is in progress. That way all other states can
595
774
  * happily ignore interaction contexts.
596
775
  */
597
- class InteractionPopStateTransition extends AbstractInteractionTransition {
598
- constructor() {
599
- super(...arguments);
776
+ class LeavingInteractionAfterPopStateTransition extends AbstractInteractionTransition {
777
+ /**
778
+ * @param {?} context
779
+ * @param {?} startingUrl
780
+ * @param {?} poppedHistoryUrl
781
+ */
782
+ constructor(context, startingUrl, poppedHistoryUrl) {
783
+ super(context, startingUrl);
784
+ this.poppedHistoryUrl = poppedHistoryUrl;
600
785
  this.isPopState = true;
601
786
  }
602
- // @Trace()
603
787
  /**
604
788
  * @param {?} event
605
789
  * @return {?}
@@ -615,7 +799,6 @@ if (false) {
615
799
  return new Idle(this.context);
616
800
  }
617
801
  }
618
- // @Trace()
619
802
  /**
620
803
  * @param {?} event
621
804
  * @return {?}
@@ -628,26 +811,124 @@ if (false) {
628
811
  return new Idle(this.context);
629
812
  }
630
813
  }
814
+ /**
815
+ * @param {?} newUrl
816
+ * @return {?}
817
+ */
818
+ createNavigationInteractionCancelledState(newUrl) {
819
+ return this.illegalTransition("Leaving interaction after pop-state should't block so should never see a back button click");
820
+ }
631
821
  }
632
- NavigationState.InteractionPopStateTransition = InteractionPopStateTransition;
822
+ NavigationState.LeavingInteractionAfterPopStateTransition = LeavingInteractionAfterPopStateTransition;
633
823
  if (false) {
634
824
  /** @type {?} */
635
- InteractionPopStateTransition.prototype.isPopState;
825
+ LeavingInteractionAfterPopStateTransition.prototype.isPopState;
826
+ /** @type {?} */
827
+ LeavingInteractionAfterPopStateTransition.prototype.poppedHistoryUrl;
636
828
  }
637
- class CancelledDuringNavigationInteraction extends NavigationState {
829
+ // See LeavingInteractionAfterPopStateTransition.createNavigationInteractionCancelledState(...) above.
830
+ //
831
+ // export class LeavingInteractionAfterPopStateCancelled extends NavigationState {
832
+ //
833
+ // readonly isPopState = false;
834
+ // firstCancelHandled = false;
835
+ // popStateHandled = false;
836
+ // popStateEventUrl: string;
837
+ // debugPropertyKeys = ['idle', 'startingUrl', 'poppedHistoryUrl', 'locationChangeTriggerUrl', 'popStateEventUrl', 'firstCancelHandled', 'popStateHandled'];
838
+ //
839
+ // constructor(context: Context,
840
+ // readonly startingUrl: string,
841
+ // readonly locationChangeTriggerUrl: string,
842
+ // readonly poppedHistoryUrl: string) {
843
+ // super(context);
844
+ // }
845
+ //
846
+ // get isTransitional() {
847
+ // return true;
848
+ // }
849
+ //
850
+ // onRouterStarted(event: NavigationStart): NavigationState {
851
+ // return this.ignore(event);
852
+ // }
853
+ //
854
+ //
855
+ // onRouterCancelled(event: NavigationCancel): NavigationState {
856
+ //
857
+ // // if (this.firstCancelHandled && this.popStateHandled) {
858
+ // // // Angular doesn't preserve the url when a guard cancels the back button.
859
+ // // // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
860
+ // // Logger.get(this).info('WORK-AROUND: Updating browser location after pop state - see angular issue #13586');
861
+ // // this.resetBrowserLocation(this.locationChangeTriggerUrl); // put the second back click one back in.
862
+ // // this.resetBrowserLocation(this.poppedHistoryUrl); // put the first back click one back in.
863
+ // // if (this.interactionService.isActive()) {
864
+ // // const interactionIds = this.interactionService.activeInteractionContextIds.value;
865
+ // // this.resetBrowserLocation(this.placeRouter.parseUrl(this.startingUrl).updateInteractionIds(interactionIds).url);
866
+ // // } else {
867
+ // // this.resetBrowserLocation(this.startingUrl); // and now put our own url back in.
868
+ // // }
869
+ // // return this.createIdleState();
870
+ // // } else {
871
+ // // this.firstCancelHandled = true;
872
+ // return this.ignore(event);
873
+ // // }
874
+ // }
875
+ //
876
+ //
877
+ // onRouterEnd(event: NavigationEnd): NavigationState {
878
+ // return this.ignore(event);
879
+ // }
880
+ //
881
+ //
882
+ // onRouterError(event: NavigationError): NavigationState {
883
+ // return this.ignore(event);
884
+ // }
885
+ //
886
+ //
887
+ // onPopState(event: NavigationStart): NavigationState {
888
+ // // this.popStateHandled = true;
889
+ // // this.popStateEventUrl = event.url;
890
+ // return this.ignore(event);
891
+ // }
892
+ //
893
+ // async canDeactivatePlace(component: PlaceComponent, currentUrl: UrlSnapshot, nextUrl: UrlSnapshot): Promise<boolean | UrlSnapshot> {
894
+ // return false;
895
+ // }
896
+ // }
897
+ /**
898
+ * This state handles the scenario where a link navigation triggered an interaction and the user clicked back a to cancel it.
899
+ * The routing event sequence is different depending on the link that was clicked.
900
+ *
901
+ * If the link was the same as the previous history location (i.e. they've gone back via a link rather than clicking back) then the sequence is:
902
+ *
903
+ * -> Idle -> NavigationTransition
904
+ * -> confirm dialog shown.
905
+ * -> click back
906
+ * -> NavigationCancel -> clickedLinkUrl === cancel.url
907
+ * -> NavigationEnd
908
+ *
909
+ * Otherwise if the link is different from teh history location then the sequence is:
910
+ *
911
+ * -> Idle -> NavigationTransition
912
+ * -> confirm dialog shown.
913
+ * -> click back
914
+ * -> NavigationCancel -> clickedLinkUrl !== cancel.url
915
+ * -> NavigationEnd
916
+ * -> PopState
917
+ * -> NavigationCancel
918
+ */
919
+ class LinkTriggeredNavigationInteractionCancelled extends NavigationState {
638
920
  /**
639
921
  * @param {?} context
640
922
  * @param {?} startingUrl
641
- * @param {?} startingEventWasAPopState
642
- * @param {?} locationChangeTriggerUrl
923
+ * @param {?} clickedLinkUrl
643
924
  */
644
- constructor(context, startingUrl, startingEventWasAPopState, locationChangeTriggerUrl) {
925
+ constructor(context, startingUrl, clickedLinkUrl) {
645
926
  super(context);
646
927
  this.startingUrl = startingUrl;
647
- this.startingEventWasAPopState = startingEventWasAPopState;
648
- this.locationChangeTriggerUrl = locationChangeTriggerUrl;
928
+ this.clickedLinkUrl = clickedLinkUrl;
649
929
  this.isPopState = false;
650
- this.gotPopStateWithLeavingUrl = false;
930
+ this.clickedLinkMatchedBackButtonUrl = false;
931
+ this.debugPropertyKeys = ['idle', 'startingUrl', 'clickedLinkUrl', 'firstCancelEventUrl', 'clickedLinkMatchedBackButtonUrl', 'popStateEventUrl'];
651
932
  }
652
933
  /**
653
934
  * @return {?}
@@ -662,29 +943,35 @@ if (false) {
662
943
  onRouterStarted(event) {
663
944
  return this.ignore(event);
664
945
  }
665
- // @Trace()
666
946
  /**
667
947
  * @param {?} event
668
948
  * @return {?}
669
949
  */
670
950
  onRouterCancelled(event) {
671
- // Depending on the state of the router and what was done we get a different
672
- // sequence of events.
673
- // If the navigation change was triggered by clicking a link we'll get a cancel with the locationChangeTriggerUrl as the final event.
674
- // If the navigation change was triggered with a pop state then we'll get an onPopState with the locationChangeTriggerUrl but no cancel event with it.
675
- if (this.gotPopStateWithLeavingUrl && this.interactionService.isActive()) {
676
- /** @type {?} */
677
- const interactionIds = this.interactionService.activeInteractionContextIds.value;
678
- this.resetBrowserLocation(this.placeRouter.parseUrl(this.startingUrl).updateInteractionIds(interactionIds).url);
951
+ // TODO: should really split this into two sub states in the first cancel event.
952
+ if (!this.firstCancelEventUrl) {
953
+ this.firstCancelEventUrl = event.url;
954
+ this.clickedLinkMatchedBackButtonUrl = event.url === this.clickedLinkUrl;
955
+ return this.ignore(event);
956
+ }
957
+ else {
958
+ // we wait for our popped state to come in.
959
+ if (!this.clickedLinkMatchedBackButtonUrl && this.popStateEventUrl) {
960
+ return this.finaliseRouting();
961
+ }
679
962
  }
680
- return this.gotPopStateWithLeavingUrl || this.locationChangeTriggerUrl === event.url ? this.createIdleState() : this.ignore(event);
681
963
  }
682
964
  /**
683
965
  * @param {?} event
684
966
  * @return {?}
685
967
  */
686
968
  onRouterEnd(event) {
687
- return this.ignore(event);
969
+ if (this.clickedLinkMatchedBackButtonUrl) {
970
+ return this.finaliseRouting();
971
+ }
972
+ else {
973
+ return this.ignore(event);
974
+ }
688
975
  }
689
976
  /**
690
977
  * @param {?} event
@@ -698,10 +985,27 @@ if (false) {
698
985
  * @return {?}
699
986
  */
700
987
  onPopState(event) {
701
- this.gotPopStateWithLeavingUrl = this.gotPopStateWithLeavingUrl || event.url === this.locationChangeTriggerUrl;
988
+ this.popStateEventUrl = event.url;
702
989
  return this.ignore(event);
703
990
  }
704
- // @Trace()
991
+ /**
992
+ * @return {?}
993
+ */
994
+ finaliseRouting() {
995
+ Logger.get(this).info('WORK-AROUND: Updating browser location after pop state - see angular issue #13586');
996
+ this.resetBrowserLocation(this.clickedLinkUrl); // put the back click one back in.
997
+ if (this.interactionService.isActive()) {
998
+ /** @type {?} */
999
+ const interactionIds = this.interactionService.activeInteractionContextIds.value;
1000
+ // Angular doesn't preserve the url when a guard cancels the back button.
1001
+ // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
1002
+ this.resetBrowserLocation(this.placeRouter.parseUrl(this.startingUrl).updateInteractionIds(interactionIds).url);
1003
+ }
1004
+ else {
1005
+ this.resetBrowserLocation(this.startingUrl); // and now put our own url back in.
1006
+ }
1007
+ return this.createIdleState();
1008
+ }
705
1009
  /**
706
1010
  * @param {?} component
707
1011
  * @param {?} currentUrl
@@ -713,38 +1017,144 @@ if (false) {
713
1017
  return false;
714
1018
  });
715
1019
  }
1020
+ }
1021
+ NavigationState.LinkTriggeredNavigationInteractionCancelled = LinkTriggeredNavigationInteractionCancelled;
1022
+ if (false) {
1023
+ /** @type {?} */
1024
+ LinkTriggeredNavigationInteractionCancelled.prototype.isPopState;
1025
+ /** @type {?} */
1026
+ LinkTriggeredNavigationInteractionCancelled.prototype.firstCancelEventUrl;
1027
+ /** @type {?} */
1028
+ LinkTriggeredNavigationInteractionCancelled.prototype.popStateEventUrl;
1029
+ /** @type {?} */
1030
+ LinkTriggeredNavigationInteractionCancelled.prototype.clickedLinkMatchedBackButtonUrl;
1031
+ /** @type {?} */
1032
+ LinkTriggeredNavigationInteractionCancelled.prototype.debugPropertyKeys;
1033
+ /** @type {?} */
1034
+ LinkTriggeredNavigationInteractionCancelled.prototype.startingUrl;
1035
+ /** @type {?} */
1036
+ LinkTriggeredNavigationInteractionCancelled.prototype.clickedLinkUrl;
1037
+ }
1038
+ /**
1039
+ * This state handles the scenario where a pop state triggered and interaction and the user clickeb back a second time to cancel it.
1040
+ * The sequence of routing events/state transitions is as follows.
1041
+ * -> Idle -> PopStateTransition (poppedHistoryUrl == page to go to, startingUrl = page to stay on )
1042
+ * -> confirm dialog shown.
1043
+ * -> click back
1044
+ * -> PopStateTransition -> CancelledDuringBackButtonNavigationInteraction(trigger url is the page before the popped history url)
1045
+ * -> NavigationCancel (for the previous back)
1046
+ * -> PopState
1047
+ * -> NavigationCancel
1048
+ */
1049
+ class PopStateTriggeredNavigationInteractionCancelled extends NavigationState {
1050
+ /**
1051
+ * @param {?} context
1052
+ * @param {?} startingUrl
1053
+ * @param {?} locationChangeTriggerUrl
1054
+ * @param {?} poppedHistoryUrl
1055
+ */
1056
+ constructor(context, startingUrl, locationChangeTriggerUrl, poppedHistoryUrl) {
1057
+ super(context);
1058
+ this.startingUrl = startingUrl;
1059
+ this.locationChangeTriggerUrl = locationChangeTriggerUrl;
1060
+ this.poppedHistoryUrl = poppedHistoryUrl;
1061
+ this.isPopState = false;
1062
+ this.firstCancelHandled = false;
1063
+ this.popStateHandled = false;
1064
+ this.debugPropertyKeys = ['idle', 'startingUrl', 'poppedHistoryUrl', 'locationChangeTriggerUrl', 'popStateEventUrl', 'firstCancelHandled', 'popStateHandled'];
1065
+ }
1066
+ /**
1067
+ * @return {?}
1068
+ */
1069
+ get isTransitional() {
1070
+ return true;
1071
+ }
716
1072
  /**
717
1073
  * @param {?} event
718
- * @param {?=} reason
719
1074
  * @return {?}
720
1075
  */
721
- ignore(event, reason) {
722
- reason = reason ? ` -> ${reason}` : '';
723
- Logger.get(this).info(`ignoring router event${reason}: ${event.constructor.name} -> ${event.url}`);
724
- return this;
1076
+ onRouterStarted(event) {
1077
+ return this.ignore(event);
725
1078
  }
726
1079
  /**
1080
+ * @param {?} event
727
1081
  * @return {?}
728
1082
  */
729
- toString() {
730
- return `${this.constructor.name}(isIdl: ${this.idle}, startingUrl: ${this.startingUrl}, locationChangeTriggerUrl:${this.locationChangeTriggerUrl})`;
1083
+ onRouterCancelled(event) {
1084
+ if (this.firstCancelHandled && this.popStateHandled) {
1085
+ // Angular doesn't preserve the url when a guard cancels the back button.
1086
+ // See https://github.com/angular/angular/issues/13586#issuecomment-432795720
1087
+ Logger.get(this).info('WORK-AROUND: Updating browser location after pop state - see angular issue #13586');
1088
+ this.resetBrowserLocation(this.locationChangeTriggerUrl); // put the second back click one back in.
1089
+ this.resetBrowserLocation(this.poppedHistoryUrl); // put the first back click one back in.
1090
+ if (this.interactionService.isActive()) {
1091
+ /** @type {?} */
1092
+ const interactionIds = this.interactionService.activeInteractionContextIds.value;
1093
+ this.resetBrowserLocation(this.placeRouter.parseUrl(this.startingUrl).updateInteractionIds(interactionIds).url);
1094
+ }
1095
+ else {
1096
+ this.resetBrowserLocation(this.startingUrl); // and now put our own url back in.
1097
+ }
1098
+ return this.createIdleState();
1099
+ }
1100
+ else {
1101
+ this.firstCancelHandled = true;
1102
+ return this.ignore(event);
1103
+ }
1104
+ }
1105
+ /**
1106
+ * @param {?} event
1107
+ * @return {?}
1108
+ */
1109
+ onRouterEnd(event) {
1110
+ return this.ignore(event);
1111
+ }
1112
+ /**
1113
+ * @param {?} event
1114
+ * @return {?}
1115
+ */
1116
+ onRouterError(event) {
1117
+ return this.ignore(event);
1118
+ }
1119
+ /**
1120
+ * @param {?} event
1121
+ * @return {?}
1122
+ */
1123
+ onPopState(event) {
1124
+ this.popStateHandled = true;
1125
+ this.popStateEventUrl = event.url;
1126
+ return this.ignore(event);
1127
+ }
1128
+ /**
1129
+ * @param {?} component
1130
+ * @param {?} currentUrl
1131
+ * @param {?} nextUrl
1132
+ * @return {?}
1133
+ */
1134
+ canDeactivatePlace(component, currentUrl, nextUrl) {
1135
+ return tslib_1.__awaiter(this, void 0, void 0, function* () {
1136
+ return false;
1137
+ });
731
1138
  }
732
1139
  }
733
- NavigationState.CancelledDuringNavigationInteraction = CancelledDuringNavigationInteraction;
1140
+ NavigationState.PopStateTriggeredNavigationInteractionCancelled = PopStateTriggeredNavigationInteractionCancelled;
734
1141
  if (false) {
735
1142
  /** @type {?} */
736
- CancelledDuringNavigationInteraction.prototype.isPopState;
737
- /**
738
- * @type {?}
739
- * @private
740
- */
741
- CancelledDuringNavigationInteraction.prototype.gotPopStateWithLeavingUrl;
1143
+ PopStateTriggeredNavigationInteractionCancelled.prototype.isPopState;
1144
+ /** @type {?} */
1145
+ PopStateTriggeredNavigationInteractionCancelled.prototype.firstCancelHandled;
1146
+ /** @type {?} */
1147
+ PopStateTriggeredNavigationInteractionCancelled.prototype.popStateHandled;
1148
+ /** @type {?} */
1149
+ PopStateTriggeredNavigationInteractionCancelled.prototype.popStateEventUrl;
1150
+ /** @type {?} */
1151
+ PopStateTriggeredNavigationInteractionCancelled.prototype.debugPropertyKeys;
742
1152
  /** @type {?} */
743
- CancelledDuringNavigationInteraction.prototype.startingUrl;
1153
+ PopStateTriggeredNavigationInteractionCancelled.prototype.startingUrl;
744
1154
  /** @type {?} */
745
- CancelledDuringNavigationInteraction.prototype.startingEventWasAPopState;
1155
+ PopStateTriggeredNavigationInteractionCancelled.prototype.locationChangeTriggerUrl;
746
1156
  /** @type {?} */
747
- CancelledDuringNavigationInteraction.prototype.locationChangeTriggerUrl;
1157
+ PopStateTriggeredNavigationInteractionCancelled.prototype.poppedHistoryUrl;
748
1158
  }
749
1159
  })(NavigationState || (NavigationState = {}));
750
1160
  //# sourceMappingURL=navigation-state.js.map