forked from EVOgeek/Vmeda.Online
		
	MOBILE-3833 user-tours: Listen to changes on scroll and resize
This commit is contained in:
		
							parent
							
								
									09c2b89c44
								
							
						
					
					
						commit
						7236dd34c1
					
				| @ -13,7 +13,17 @@ | |||||||
| // limitations under the License.
 | // limitations under the License.
 | ||||||
| 
 | 
 | ||||||
| import { BackButtonEvent } from '@ionic/core'; | import { BackButtonEvent } from '@ionic/core'; | ||||||
| import { AfterViewInit, Component, ElementRef, EventEmitter, HostBinding, Input, Output, ViewChild } from '@angular/core'; | import { | ||||||
|  |     AfterViewInit, | ||||||
|  |     Component, | ||||||
|  |     ElementRef, | ||||||
|  |     EventEmitter, | ||||||
|  |     HostBinding, | ||||||
|  |     Input, | ||||||
|  |     OnDestroy, | ||||||
|  |     Output, | ||||||
|  |     ViewChild, | ||||||
|  | } from '@angular/core'; | ||||||
| import { CorePromisedValue } from '@classes/promised-value'; | import { CorePromisedValue } from '@classes/promised-value'; | ||||||
| import { CoreUserToursFocusLayout } from '@features/usertours/classes/focus-layout'; | import { CoreUserToursFocusLayout } from '@features/usertours/classes/focus-layout'; | ||||||
| import { CoreUserToursPopoverLayout } from '@features/usertours/classes/popover-layout'; | import { CoreUserToursPopoverLayout } from '@features/usertours/classes/popover-layout'; | ||||||
| @ -22,6 +32,7 @@ import { CoreDomUtils } from '@services/utils/dom'; | |||||||
| import { AngularFrameworkDelegate } from '@singletons'; | import { AngularFrameworkDelegate } from '@singletons'; | ||||||
| import { CoreComponentsRegistry } from '@singletons/components-registry'; | import { CoreComponentsRegistry } from '@singletons/components-registry'; | ||||||
| import { CoreDom } from '@singletons/dom'; | import { CoreDom } from '@singletons/dom'; | ||||||
|  | import { CoreEventObserver } from '@singletons/events'; | ||||||
| 
 | 
 | ||||||
| const ANIMATION_DURATION = 200; | const ANIMATION_DURATION = 200; | ||||||
| const USER_TOURS_BACK_BUTTON_PRIORITY = 100; | const USER_TOURS_BACK_BUTTON_PRIORITY = 100; | ||||||
| @ -36,7 +47,7 @@ const USER_TOURS_BACK_BUTTON_PRIORITY = 100; | |||||||
|     templateUrl: 'core-user-tours-user-tour.html', |     templateUrl: 'core-user-tours-user-tour.html', | ||||||
|     styleUrls: ['user-tour.scss'], |     styleUrls: ['user-tour.scss'], | ||||||
| }) | }) | ||||||
| export class CoreUserToursUserTourComponent implements AfterViewInit { | export class CoreUserToursUserTourComponent implements AfterViewInit, OnDestroy { | ||||||
| 
 | 
 | ||||||
|     @Input() container!: HTMLElement; |     @Input() container!: HTMLElement; | ||||||
|     @Input() id!: string; |     @Input() id!: string; | ||||||
| @ -59,6 +70,9 @@ export class CoreUserToursUserTourComponent implements AfterViewInit { | |||||||
|     private wrapperTransform = ''; |     private wrapperTransform = ''; | ||||||
|     private wrapperElement = new CorePromisedValue<HTMLElement>(); |     private wrapperElement = new CorePromisedValue<HTMLElement>(); | ||||||
|     private backButtonListener?: (event: BackButtonEvent) => void; |     private backButtonListener?: (event: BackButtonEvent) => void; | ||||||
|  |     protected resizeListener?: CoreEventObserver; | ||||||
|  |     protected scrollListener?: EventListener; | ||||||
|  |     protected content?: HTMLIonContentElement | null; | ||||||
| 
 | 
 | ||||||
|     constructor({ nativeElement: element }: ElementRef<HTMLElement>) { |     constructor({ nativeElement: element }: ElementRef<HTMLElement>) { | ||||||
|         this.element = element; |         this.element = element; | ||||||
| @ -100,18 +114,7 @@ export class CoreUserToursUserTourComponent implements AfterViewInit { | |||||||
| 
 | 
 | ||||||
|         this.calculateStyles(); |         this.calculateStyles(); | ||||||
| 
 | 
 | ||||||
|         // Show tour.
 |         this.activate(); | ||||||
|         this.active = true; |  | ||||||
| 
 |  | ||||||
|         document.addEventListener( |  | ||||||
|             'ionBackButton', |  | ||||||
|             this.backButtonListener = ({ detail }) => detail.register( |  | ||||||
|                 USER_TOURS_BACK_BUTTON_PRIORITY, |  | ||||||
|                 () => { |  | ||||||
|                     // Silence back button.
 |  | ||||||
|                 }, |  | ||||||
|             ), |  | ||||||
|         ); |  | ||||||
| 
 | 
 | ||||||
|         await this.playEnterAnimation(); |         await this.playEnterAnimation(); | ||||||
|     } |     } | ||||||
| @ -125,8 +128,7 @@ export class CoreUserToursUserTourComponent implements AfterViewInit { | |||||||
|         await this.playLeaveAnimation(); |         await this.playLeaveAnimation(); | ||||||
|         await AngularFrameworkDelegate.removeViewFromDom(wrapper, this.tour); |         await AngularFrameworkDelegate.removeViewFromDom(wrapper, this.tour); | ||||||
| 
 | 
 | ||||||
|         this.active = false; |         this.deactivate(); | ||||||
|         this.backButtonListener && document.removeEventListener('ionBackButton', this.backButtonListener); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -139,11 +141,11 @@ export class CoreUserToursUserTourComponent implements AfterViewInit { | |||||||
| 
 | 
 | ||||||
|         if (this.active) { |         if (this.active) { | ||||||
|             await this.playLeaveAnimation(); |             await this.playLeaveAnimation(); | ||||||
|             await AngularFrameworkDelegate.removeViewFromDom(this.container, this.element); |  | ||||||
| 
 |  | ||||||
|             this.backButtonListener && document.removeEventListener('ionBackButton', this.backButtonListener); |  | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|  |         await AngularFrameworkDelegate.removeViewFromDom(this.container, this.element); | ||||||
|  |         this.deactivate(); | ||||||
|  | 
 | ||||||
|         acknowledge && await CoreUserTours.acknowledge(this.id); |         acknowledge && await CoreUserTours.acknowledge(this.id); | ||||||
| 
 | 
 | ||||||
|         this.afterDismiss.emit(); |         this.afterDismiss.emit(); | ||||||
| @ -205,4 +207,76 @@ export class CoreUserToursUserTourComponent implements AfterViewInit { | |||||||
|         await Promise.all(animations.map(animation => animation?.finished)); |         await Promise.all(animations.map(animation => animation?.finished)); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * @inheritdoc | ||||||
|  |      */ | ||||||
|  |     ngOnDestroy(): void { | ||||||
|  |         this.deactivate(); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Activate tour. | ||||||
|  |      */ | ||||||
|  |     protected activate(): void { | ||||||
|  |         if (this.active) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.active = true; | ||||||
|  | 
 | ||||||
|  |         if (!this.backButtonListener) { | ||||||
|  |             document.addEventListener( | ||||||
|  |                 'ionBackButton', | ||||||
|  |                 this.backButtonListener = ({ detail }) => detail.register( | ||||||
|  |                     USER_TOURS_BACK_BUTTON_PRIORITY, | ||||||
|  |                     () => { | ||||||
|  |                         // Silence back button.
 | ||||||
|  |                     }, | ||||||
|  |                 ), | ||||||
|  |             ); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!this.focus) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!this.resizeListener) { | ||||||
|  |             this.resizeListener = CoreDom.onWindowResize(() => { | ||||||
|  |                 this.calculateStyles(); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!this.content) { | ||||||
|  |             this.content = CoreDom.closest(this.focus, 'ion-content'); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (!this.scrollListener && this.content) { | ||||||
|  |             this.content.scrollEvents = true; | ||||||
|  | 
 | ||||||
|  |             this.content.addEventListener('ionScrollEnd', this.scrollListener = (): void => { | ||||||
|  |                 this.calculateStyles(); | ||||||
|  |             }); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Deactivate tour. | ||||||
|  |      */ | ||||||
|  |     protected deactivate(): void { | ||||||
|  |         if (!this.active) { | ||||||
|  |             return; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         this.active = false; | ||||||
|  | 
 | ||||||
|  |         this.resizeListener?.off(); | ||||||
|  |         this.backButtonListener && document.removeEventListener('ionBackButton', this.backButtonListener); | ||||||
|  |         this.backButtonListener = undefined; | ||||||
|  |         this.resizeListener = undefined; | ||||||
|  | 
 | ||||||
|  |         if (this.content && this.scrollListener) { | ||||||
|  |             this.content.removeEventListener('ionScrollEnd', this.scrollListener); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  | 
 | ||||||
| } | } | ||||||
|  | |||||||
| @ -27,6 +27,33 @@ export class CoreDom { | |||||||
|         // Nothing to do.
 |         // Nothing to do.
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Perform a dom closest function piercing the shadow DOM. | ||||||
|  |      * | ||||||
|  |      * @param node DOM Element. | ||||||
|  |      * @param selector Selector to search. | ||||||
|  |      * @return Closest ancestor or null if not found. | ||||||
|  |      */ | ||||||
|  |     static closest<T = HTMLElement>(node: HTMLElement | Node | null, selector: string): T | null { | ||||||
|  |         if (!node) { | ||||||
|  |             return null; | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (node instanceof ShadowRoot) { | ||||||
|  |             return CoreDom.closest(node.host, selector); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (node instanceof HTMLElement) { | ||||||
|  |             if (node.matches(selector)) { | ||||||
|  |                 return node as unknown as T; | ||||||
|  |             } else { | ||||||
|  |                 return CoreDom.closest<T>(node.parentNode, selector); | ||||||
|  |             } | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         return CoreDom.closest<T>(node.parentNode, selector); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Retrieve the position of a element relative to another element. |      * Retrieve the position of a element relative to another element. | ||||||
|      * |      * | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user