UNPKG

@ionic/angular

Version:

Angular specific wrappers for @ionic/core

180 lines 22 kB
import { Component, ContentChild, ContentChildren, ElementRef, EventEmitter, HostListener, Output, ViewChild, } from '@angular/core'; import { IonTabBar } from '../proxies'; import { IonRouterOutlet } from './ion-router-outlet'; import * as i0 from "@angular/core"; import * as i1 from "../../providers/nav-controller"; import * as i2 from "./ion-router-outlet"; // eslint-disable-next-line @angular-eslint/component-class-suffix export class IonTabs { constructor(navCtrl) { this.navCtrl = navCtrl; this.ionTabsWillChange = new EventEmitter(); this.ionTabsDidChange = new EventEmitter(); this.tabBarSlot = 'bottom'; } ngAfterContentInit() { this.detectSlotChanges(); } ngAfterContentChecked() { this.detectSlotChanges(); } /** * @internal */ onPageSelected(detail) { const stackId = detail.enteringView.stackId; if (detail.tabSwitch && stackId !== undefined) { this.ionTabsWillChange.emit({ tab: stackId }); if (this.tabBar) { this.tabBar.selectedTab = stackId; } this.ionTabsDidChange.emit({ tab: stackId }); } } /** * When a tab button is clicked, there are several scenarios: * 1. If the selected tab is currently active (the tab button has been clicked * again), then it should go to the root view for that tab. * * a. Get the saved root view from the router outlet. If the saved root view * matches the tabRootUrl, set the route view to this view including the * navigation extras. * b. If the saved root view from the router outlet does * not match, navigate to the tabRootUrl. No navigation extras are * included. * * 2. If the current tab tab is not currently selected, get the last route * view from the router outlet. * * a. If the last route view exists, navigate to that view including any * navigation extras * b. If the last route view doesn't exist, then navigate * to the default tabRootUrl */ select(tabOrEvent) { const isTabString = typeof tabOrEvent === 'string'; const tab = isTabString ? tabOrEvent : tabOrEvent.detail.tab; const alreadySelected = this.outlet.getActiveStackId() === tab; const tabRootUrl = `${this.outlet.tabsPrefix}/${tab}`; /** * If this is a nested tab, prevent the event * from bubbling otherwise the outer tabs * will respond to this event too, causing * the app to get directed to the wrong place. */ if (!isTabString) { tabOrEvent.stopPropagation(); } if (alreadySelected) { const activeStackId = this.outlet.getActiveStackId(); const activeView = this.outlet.getLastRouteView(activeStackId); // If on root tab, do not navigate to root tab again if (activeView?.url === tabRootUrl) { return; } const rootView = this.outlet.getRootView(tab); const navigationExtras = rootView && tabRootUrl === rootView.url && rootView.savedExtras; return this.navCtrl.navigateRoot(tabRootUrl, { ...navigationExtras, animated: true, animationDirection: 'back', }); } else { const lastRoute = this.outlet.getLastRouteView(tab); /** * If there is a lastRoute, goto that, otherwise goto the fallback url of the * selected tab */ const url = lastRoute?.url || tabRootUrl; const navigationExtras = lastRoute?.savedExtras; return this.navCtrl.navigateRoot(url, { ...navigationExtras, animated: true, animationDirection: 'back', }); } } getSelected() { return this.outlet.getActiveStackId(); } /** * Detects changes to the slot attribute of the tab bar. * * If the slot attribute has changed, then the tab bar * should be relocated to the new slot position. */ detectSlotChanges() { this.tabBars.forEach((tabBar) => { // el is a protected attribute from the generated component wrapper const currentSlot = tabBar.el.getAttribute('slot'); if (currentSlot !== this.tabBarSlot) { this.tabBarSlot = currentSlot; this.relocateTabBar(); } }); } /** * Relocates the tab bar to the new slot position. */ relocateTabBar() { /** * `el` is a protected attribute from the generated component wrapper. * To avoid having to manually create the wrapper for tab bar, we * cast the tab bar to any and access the protected attribute. */ const tabBar = this.tabBar.el; if (this.tabBarSlot === 'top') { /** * A tab bar with a slot of "top" should be inserted * at the top of the container. */ this.tabsInner.nativeElement.before(tabBar); } else { /** * A tab bar with a slot of "bottom" or without a slot * should be inserted at the end of the container. */ this.tabsInner.nativeElement.after(tabBar); } } } /** @nocollapse */ IonTabs.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonTabs, deps: [{ token: i1.NavController }], target: i0.ɵɵFactoryTarget.Component }); /** @nocollapse */ IonTabs.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "14.2.12", type: IonTabs, selector: "ion-tabs", outputs: { ionTabsWillChange: "ionTabsWillChange", ionTabsDidChange: "ionTabsDidChange" }, host: { listeners: { "ionTabButtonClick": "select($event)" } }, queries: [{ propertyName: "tabBar", first: true, predicate: IonTabBar, descendants: true }, { propertyName: "tabBars", predicate: IonTabBar }], viewQueries: [{ propertyName: "outlet", first: true, predicate: ["outlet"], descendants: true, read: IonRouterOutlet }, { propertyName: "tabsInner", first: true, predicate: ["tabsInner"], descendants: true, read: ElementRef, static: true }], ngImport: i0, template: ` <ng-content select="[slot=top]"></ng-content> <div class="tabs-inner" #tabsInner> <ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet> </div> <ng-content></ng-content> `, isInline: true, styles: [":host{display:flex;position:absolute;inset:0;flex-direction:column;width:100%;height:100%;contain:layout size style}.tabs-inner{position:relative;flex:1;contain:layout size style}\n"], dependencies: [{ kind: "directive", type: i2.IonRouterOutlet, selector: "ion-router-outlet", inputs: ["animated", "animation", "mode", "swipeGesture"], outputs: ["stackEvents", "activate", "deactivate"], exportAs: ["outlet"] }] }); i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "14.2.12", ngImport: i0, type: IonTabs, decorators: [{ type: Component, args: [{ selector: 'ion-tabs', template: ` <ng-content select="[slot=top]"></ng-content> <div class="tabs-inner" #tabsInner> <ion-router-outlet #outlet tabs="true" (stackEvents)="onPageSelected($event)"></ion-router-outlet> </div> <ng-content></ng-content> `, styles: [":host{display:flex;position:absolute;inset:0;flex-direction:column;width:100%;height:100%;contain:layout size style}.tabs-inner{position:relative;flex:1;contain:layout size style}\n"] }] }], ctorParameters: function () { return [{ type: i1.NavController }]; }, propDecorators: { outlet: [{ type: ViewChild, args: ['outlet', { read: IonRouterOutlet, static: false }] }], tabsInner: [{ type: ViewChild, args: ['tabsInner', { read: ElementRef, static: true }] }], tabBar: [{ type: ContentChild, args: [IonTabBar, { static: false }] }], tabBars: [{ type: ContentChildren, args: [IonTabBar] }], ionTabsWillChange: [{ type: Output }], ionTabsDidChange: [{ type: Output }], select: [{ type: HostListener, args: ['ionTabButtonClick', ['$event']] }] } }); //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiaW9uLXRhYnMuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi9zcmMvZGlyZWN0aXZlcy9uYXZpZ2F0aW9uL2lvbi10YWJzLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFHTCxTQUFTLEVBQ1QsWUFBWSxFQUNaLGVBQWUsRUFDZixVQUFVLEVBQ1YsWUFBWSxFQUNaLFlBQVksRUFDWixNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBR3ZCLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSxZQUFZLENBQUM7QUFFdkMsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDOzs7O0FBdUN0RCxrRUFBa0U7QUFDbEUsTUFBTSxPQUFPLE9BQU87SUFZbEIsWUFBb0IsT0FBc0I7UUFBdEIsWUFBTyxHQUFQLE9BQU8sQ0FBZTtRQUxoQyxzQkFBaUIsR0FBRyxJQUFJLFlBQVksRUFBbUIsQ0FBQztRQUN4RCxxQkFBZ0IsR0FBRyxJQUFJLFlBQVksRUFBbUIsQ0FBQztRQUV6RCxlQUFVLEdBQUcsUUFBUSxDQUFDO0lBRWUsQ0FBQztJQUU5QyxrQkFBa0I7UUFDaEIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7SUFDM0IsQ0FBQztJQUVELHFCQUFxQjtRQUNuQixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztJQUMzQixDQUFDO0lBRUQ7O09BRUc7SUFDSCxjQUFjLENBQUMsTUFBa0I7UUFDL0IsTUFBTSxPQUFPLEdBQUcsTUFBTSxDQUFDLFlBQVksQ0FBQyxPQUFPLENBQUM7UUFDNUMsSUFBSSxNQUFNLENBQUMsU0FBUyxJQUFJLE9BQU8sS0FBSyxTQUFTLEVBQUU7WUFDN0MsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksQ0FBQyxFQUFFLEdBQUcsRUFBRSxPQUFPLEVBQUUsQ0FBQyxDQUFDO1lBQzlDLElBQUksSUFBSSxDQUFDLE1BQU0sRUFBRTtnQkFDZixJQUFJLENBQUMsTUFBTSxD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aUIsQ0FBQztRQUV0RCxJQUFJLElBQUksQ0FBQyxVQUFVLEtBQUssS0FBSyxFQUFFO1lBQzdCOzs7ZUFHRztZQUNILElBQUksQ0FBQyxTQUFTLENBQUMsYUFBYSxDQUFDLE1BQU0sQ0FBQyxNQUFNLENBQUMsQ0FBQztTQUM3QzthQUFNO1lBQ0w7OztlQUdHO1lBQ0gsSUFBSSxDQUFDLFNBQVMsQ0FBQyxhQUFhLENBQUMsS0FBSyxDQUFDLE1BQU0sQ0FBQyxDQUFDO1NBQzVDO0lBQ0gsQ0FBQzs7d0hBeEpVLE9BQU87NEdBQVAsT0FBTywrT0FJSixTQUFTLDZEQUNOLFNBQVMsMEdBSkcsZUFBZSxpR0FDWixVQUFVLDJDQXJDaEM7Ozs7OztHQU1UOzRGQTZCVSxPQUFPO2tCQXJDbkIsU0FBUzsrQkFDRSxVQUFVLFlBQ1Y7Ozs7OztHQU1UO29HQThCOEQsTUFBTTtzQkFBcEUsU0FBUzt1QkFBQyxRQUFRLEVBQUUsRUFBRSxJQUFJLEVBQUUsZUFBZSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQUU7Z0JBQ0QsU0FBUztzQkFBcEUsU0FBUzt1QkFBQyxXQUFXLEVBQUUsRUFBRSxJQUFJLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUU7Z0JBRWQsTUFBTTtzQkFBakQsWUFBWTt1QkFBQyxTQUFTLEVBQUUsRUFBRSxNQUFNLEVBQUUsS0FBSyxFQUFFO2dCQUNkLE9BQU87c0JBQWxDLGVBQWU7dUJBQUMsU0FBUztnQkFFaEIsaUJBQWlCO3NCQUExQixNQUFNO2dCQUNHLGdCQUFnQjtzQkFBekIsTUFBTTtnQkFpRFAsTUFBTTtzQkFETCxZQUFZO3VCQUFDLG1CQUFtQixFQUFFLENBQUMsUUFBUSxDQUFDIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHtcbiAgQWZ0ZXJDb250ZW50Q2hlY2tlZCxcbiAgQWZ0ZXJDb250ZW50SW5pdCxcbiAgQ29tcG9uZW50LFxuICBDb250ZW50Q2hpbGQsXG4gIENvbnRlbnRDaGlsZHJlbixcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBIb3N0TGlzdGVuZXIsXG4gIE91dHB1dCxcbiAgUXVlcnlMaXN0LFxuICBWaWV3Q2hpbGQsXG59IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuXG5pbXBvcnQgeyBOYXZDb250cm9sbGVyIH0gZnJvbSAnLi4vLi4vcHJvdmlkZXJzL25hdi1jb250cm9sbGVyJztcbmltcG9ydCB7IElvblRhYkJhciB9IGZyb20gJy4uL3Byb3hpZXMnO1xuXG5pbXBvcnQgeyBJb25Sb3V0ZXJPdXRsZXQgfSBmcm9tICcuL2lvbi1yb3V0ZXItb3V0bGV0JztcbmltcG9ydCB7IFN0YWNrRXZlbnQgfSBmcm9tICcuL3N0YWNrLXV0aWxzJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnaW9uLXRhYnMnLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxuZy1jb250ZW50IHNlbGVjdD1cIltzbG90PXRvcF1cIj48L25nLWNvbnRlbnQ+XG4gICAgPGRpdiBjbGFzcz1cInRhYnMtaW5uZXJcIiAjdGFic0lubmVyPlxuICAgICAgPGlvbi1yb3V0ZXItb3V0bGV0ICNvdXRsZXQgdGFicz1cInRydWVcIiAoc3RhY2tFdmVudHMpPVwib25QYWdlU2VsZWN0ZWQoJGV2ZW50KVwiPjwvaW9uLXJvdXRlci1vdXRsZXQ+XG4gICAgPC9kaXY+XG4gICAgPG5nLWNvbnRlbnQ+PC9uZy1jb250ZW50PlxuICBgLFxuICBzdHlsZXM6IFtcbiAgICBgXG4gICAgICA6aG9zdCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIHBvc2l0aW9uOiBhYnNvbHV0ZTtcbiAgICAgICAgdG9wOiAwO1xuICAgICAgICBsZWZ0OiAwO1xuICAgICAgICByaWdodDogMDtcbiAgICAgICAgYm90dG9tOiAwO1xuXG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG5cbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGhlaWdodDogMTAwJTtcblxuICAgICAgICBjb250YWluOiBsYXlvdXQgc2l6ZSBzdHlsZTtcbiAgICAgIH1cbiAgICAgIC50YWJzLWlubmVyIHtcbiAgICAgICAgcG9zaXRpb246IHJlbGF0aXZlO1xuXG4gICAgICAgIGZsZXg6IDE7XG5cbiAgICAgICAgY29udGFpbjogbGF5b3V0IHNpemUgc3R5bGU7XG4gICAgICB9XG4gICAgYCxcbiAgXSxcbn0pXG4vLyBlc2xpbnQtZGlzYWJsZS1uZXh0LWxpbmUgQGFuZ3VsYXItZXNsaW50L2NvbXBvbmVudC1jbGFzcy1zdWZmaXhcbmV4cG9ydCBjbGFzcyBJb25UYWJzIGltcGxlbWVudHMgQWZ0ZXJDb250ZW50SW5pdCwgQWZ0ZXJDb250ZW50Q2hlY2tlZCB7XG4gIEBWaWV3Q2hpbGQoJ291dGxldCcsIHsgcmVhZDogSW9uUm91dGVyT3V0bGV0LCBzdGF0aWM6IGZhbHNlIH0pIG91dGxldDogSW9uUm91dGVyT3V0bGV0O1xuICBAVmlld0NoaWxkKCd0YWJzSW5uZXInLCB7IHJlYWQ6IEVsZW1lbnRSZWYsIHN0YXRpYzogdHJ1ZSB9KSB0YWJzSW5uZXI6IEVsZW1lbnRSZWY8SFRNTERpdkVsZW1lbnQ+O1xuXG4gIEBDb250ZW50Q2hpbGQoSW9uVGFiQmFyLCB7IHN0YXRpYzogZmFsc2UgfSkgdGFiQmFyOiBJb25UYWJCYXIgfCB1bmRlZmluZWQ7XG4gIEBDb250ZW50Q2hpbGRyZW4oSW9uVGFiQmFyKSB0YWJCYXJzOiBRdWVyeUxpc3Q8SW9uVGFiQmFyPjtcblxuICBAT3V0cHV0KCkgaW9uVGFic1dpbGxDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHsgdGFiOiBzdHJpbmcgfT4oKTtcbiAgQE91dHB1dCgpIGlvblRhYnNEaWRDaGFuZ2UgPSBuZXcgRXZlbnRFbWl0dGVyPHsgdGFiOiBzdHJpbmcgfT4oKTtcblxuICBwcml2YXRlIHRhYkJhclNsb3QgPSAnYm90dG9tJztcblxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIG5hdkN0cmw6IE5hdkNvbnRyb2xsZXIpIHt9XG5cbiAgbmdBZnRlckNvbnRlbnRJbml0KCk6IHZvaWQge1xuICAgIHRoaXMuZGV0ZWN0U2xvdENoYW5nZXMoKTtcbiAgfVxuXG4gIG5nQWZ0ZXJDb250ZW50Q2hlY2tlZCgpOiB2b2lkIHtcbiAgICB0aGlzLmRldGVjdFNsb3RDaGFuZ2VzKCk7XG4gIH1cblxuICAvKipcbiAgICogQGludGVybmFsXG4gICAqL1xuICBvblBhZ2VTZWxlY3RlZChkZXRhaWw6IFN0YWNrRXZlbnQpOiB2b2lkIHtcbiAgICBjb25zdCBzdGFja0lkID0gZGV0YWlsLmVudGVyaW5nVmlldy5zdGFja0lkO1xuICAgIGlmIChkZXRhaWwudGFiU3dpdGNoICYmIHN0YWNrSWQgIT09IHVuZGVmaW5lZCkge1xuICAgICAgdGhpcy5pb25UYWJzV2lsbENoYW5nZS5lbWl0KHsgdGFiOiBzdGFja0lkIH0pO1xuICAgICAgaWYgKHRoaXMudGFiQmFyKSB7XG4gICAgICAgIHRoaXMudGFiQmFyLnNlbGVjdGVkVGFiID0gc3RhY2tJZDtcbiAgICAgIH1cbiAgICAgIHRoaXMuaW9uVGFic0RpZENoYW5nZS5lbWl0KHsgdGFiOiBzdGFja0lkIH0pO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBXaGVuIGEgdGFiIGJ1dHRvbiBpcyBjbGlja2VkLCB0aGVyZSBhcmUgc2V2ZXJhbCBzY2VuYXJpb3M6XG4gICAqIDEuIElmIHRoZSBzZWxlY3RlZCB0YWIgaXMgY3VycmVudGx5IGFjdGl2ZSAodGhlIHRhYiBidXR0b24gaGFzIGJlZW4gY2xpY2tlZFxuICAgKiAgICBhZ2FpbiksIHRoZW4gaXQgc2hvdWxkIGdvIHRvIHRoZSByb290IHZpZXcgZm9yIHRoYXQgdGFiLlxuICAgKlxuICAgKiAgIGEuIEdldCB0aGUgc2F2ZWQgcm9vdCB2aWV3IGZyb20gdGhlIHJvdXRlciBvdXRsZXQuIElmIHRoZSBzYXZlZCByb290IHZpZXdcbiAgICogICAgICBtYXRjaGVzIHRoZSB0YWJSb290VXJsLCBzZXQgdGhlIHJvdXRlIHZpZXcgdG8gdGhpcyB2aWV3IGluY2x1ZGluZyB0aGVcbiAgICogICAgICBuYXZpZ2F0aW9uIGV4dHJhcy5cbiAgICogICBiLiBJZiB0aGUgc2F2ZWQgcm9vdCB2aWV3IGZyb20gdGhlIHJvdXRlciBvdXRsZXQgZG9lc1xuICAgKiAgICAgIG5vdCBtYXRjaCwgbmF2aWdhdGUgdG8gdGhlIHRhYlJvb3RVcmwuIE5vIG5hdmlnYXRpb24gZXh0cmFzIGFyZVxuICAgKiAgICAgIGluY2x1ZGVkLlxuICAgKlxuICAgKiAyLiBJZiB0aGUgY3VycmVudCB0YWIgdGFiIGlzIG5vdCBjdXJyZW50bHkgc2VsZWN0ZWQsIGdldCB0aGUgbGFzdCByb3V0ZVxuICAgKiAgICB2aWV3IGZyb20gdGhlIHJvdXRlciBvdXRsZXQuXG4gICAqXG4gICAqICAgYS4gSWYgdGhlIGxhc3Qgcm91dGUgdmlldyBleGlzdHMsIG5hdmlnYXRlIHRvIHRoYXQgdmlldyBpbmNsdWRpbmcgYW55XG4gICAqICAgICAgbmF2aWdhdGlvbiBleHRyYXNcbiAgICogICBiLiBJZiB0aGUgbGFzdCByb3V0ZSB2aWV3IGRvZXNuJ3QgZXhpc3QsIHRoZW4gbmF2aWdhdGVcbiAgICogICAgICB0byB0aGUgZGVmYXVsdCB0YWJSb290VXJsXG4gICAqL1xuICBASG9zdExpc3RlbmVyKCdpb25UYWJCdXR0b25DbGljaycsIFsnJGV2ZW50J10pXG4gIHNlbGVjdCh0YWJPckV2ZW50OiBzdHJpbmcgfCBDdXN0b21FdmVudCk6IFByb21pc2U8Ym9vbGVhbj4gfCB1bmRlZmluZWQge1xuICAgIGNvbnN0IGlzVGFiU3RyaW5nID0gdHlwZW9mIHRhYk9yRXZlbnQgPT09ICdzdHJpbmcnO1xuICAgIGNvbnN0IHRhYiA9IGlzVGFiU3RyaW5nID8gdGFiT3JFdmVudCA6ICh0YWJPckV2ZW50IGFzIEN1c3RvbUV2ZW50KS5kZXRhaWwudGFiO1xuICAgIGNvbnN0IGFscmVhZHlTZWxlY3RlZCA9IHRoaXMub3V0bGV0LmdldEFjdGl2ZVN0YWNrSWQoKSA9PT0gdGFiO1xuICAgIGNvbnN0IHRhYlJvb3RVcmwgPSBgJHt0aGlzLm91dGxldC50YWJzUHJlZml4fS8ke3RhYn1gO1xuXG4gICAgLyoqXG4gICAgICogSWYgdGhpcyBpcyBhIG5lc3RlZCB0YWIsIHByZXZlbnQgdGhlIGV2ZW50XG4gICAgICogZnJvbSBidWJibGluZyBvdGhlcndpc2UgdGhlIG91dGVyIHRhYnNcbiAgICAgKiB3aWxsIHJlc3BvbmQgdG8gdGhpcyBldmVudCB0b28sIGNhdXNpbmdcbiAgICAgKiB0aGUgYXBwIHRvIGdldCBkaXJlY3RlZCB0byB0aGUgd3JvbmcgcGxhY2UuXG4gICAgICovXG4gICAgaWYgKCFpc1RhYlN0cmluZykge1xuICAgICAgKHRhYk9yRXZlbnQgYXMgQ3VzdG9tRXZlbnQpLnN0b3BQcm9wYWdhdGlvbigpO1xuICAgIH1cblxuICAgIGlmIChhbHJlYWR5U2VsZWN0ZWQpIHtcbiAgICAgIGNvbnN0IGFjdGl2ZVN0YWNrSWQgPSB0aGlzLm91dGxldC5nZXRBY3RpdmVTdGFja0lkKCk7XG4gICAgICBjb25zdCBhY3RpdmVWaWV3ID0gdGhpcy5vdXRsZXQuZ2V0TGFzdFJvdXRlVmlldyhhY3RpdmVTdGFja0lkKTtcblxuICAgICAgLy8gSWYgb24gcm9vdCB0YWIsIGRvIG5vdCBuYXZpZ2F0ZSB0byByb290IHRhYiBhZ2FpblxuICAgICAgaWYgKGFjdGl2ZVZpZXc/LnVybCA9PT0gdGFiUm9vdFVybCkge1xuICAgICAgICByZXR1cm47XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IHJvb3RWaWV3ID0gdGhpcy5vdXRsZXQuZ2V0Um9vdFZpZXcodGFiKTtcbiAgICAgIGNvbnN0IG5hdmlnYXRpb25FeHRyYXMgPSByb290VmlldyAmJiB0YWJSb290VXJsID09PSByb290Vmlldy51cmwgJiYgcm9vdFZpZXcuc2F2ZWRFeHRyYXM7XG4gICAgICByZXR1cm4gdGhpcy5uYXZDdHJsLm5hdmlnYXRlUm9vdCh0YWJSb290VXJsLCB7XG4gICAgICAgIC4uLm5hdmlnYXRpb25FeHRyYXMsXG4gICAgICAgIGFuaW1hdGVkOiB0cnVlLFxuICAgICAgICBhbmltYXRpb25EaXJlY3Rpb246ICdiYWNrJyxcbiAgICAgIH0pO1xuICAgIH0gZWxzZSB7XG4gICAgICBjb25zdCBsYXN0Um91dGUgPSB0aGlzLm91dGxldC5nZXRMYXN0Um91dGVWaWV3KHRhYik7XG4gICAgICAvKipcbiAgICAgICAqIElmIHRoZXJlIGlzIGEgbGFzdFJvdXRlLCBnb3RvIHRoYXQsIG90aGVyd2lzZSBnb3RvIHRoZSBmYWxsYmFjayB1cmwgb2YgdGhlXG4gICAgICAgKiBzZWxlY3RlZCB0YWJcbiAgICAgICAqL1xuICAgICAgY29uc3QgdXJsID0gbGFzdFJvdXRlPy51cmwgfHwgdGFiUm9vdFVybDtcbiAgICAgIGNvbnN0IG5hdmlnYXRpb25FeHRyYXMgPSBsYXN0Um91dGU/LnNhdmVkRXh0cmFzO1xuXG4gICAgICByZXR1cm4gdGhpcy5uYXZDdHJsLm5hdmlnYXRlUm9vdCh1cmwsIHtcbiAgICAgICAgLi4ubmF2aWdhdGlvbkV4dHJhcyxcbiAgICAgICAgYW5pbWF0ZWQ6IHRydWUsXG4gICAgICAgIGFuaW1hdGlvbkRpcmVjdGlvbjogJ2JhY2snLFxuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgZ2V0U2VsZWN0ZWQoKTogc3RyaW5nIHwgdW5kZWZpbmVkIHtcbiAgICByZXR1cm4gdGhpcy5vdXRsZXQuZ2V0QWN0aXZlU3RhY2tJZCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIERldGVjdHMgY2hhbmdlcyB0byB0aGUgc2xvdCBhdHRyaWJ1dGUgb2YgdGhlIHRhYiBiYXIuXG4gICAqXG4gICAqIElmIHRoZSBzbG90IGF0dHJpYnV0ZSBoYXMgY2hhbmdlZCwgdGhlbiB0aGUgdGFiIGJhclxuICAgKiBzaG91bGQgYmUgcmVsb2NhdGVkIHRvIHRoZSBuZXcgc2xvdCBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgZGV0ZWN0U2xvdENoYW5nZXMoKTogdm9pZCB7XG4gICAgdGhpcy50YWJCYXJzLmZvckVhY2goKHRhYkJhcjogYW55KSA9PiB7XG4gICAgICAvLyBlbCBpcyBhIHByb3RlY3RlZCBhdHRyaWJ1dGUgZnJvbSB0aGUgZ2VuZXJhdGVkIGNvbXBvbmVudCB3cmFwcGVyXG4gICAgICBjb25zdCBjdXJyZW50U2xvdCA9IHRhYkJhci5lbC5nZXRBdHRyaWJ1dGUoJ3Nsb3QnKTtcblxuICAgICAgaWYgKGN1cnJlbnRTbG90ICE9PSB0aGlzLnRhYkJhclNsb3QpIHtcbiAgICAgICAgdGhpcy50YWJCYXJTbG90ID0gY3VycmVudFNsb3Q7XG4gICAgICAgIHRoaXMucmVsb2NhdGVUYWJCYXIoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBSZWxvY2F0ZXMgdGhlIHRhYiBiYXIgdG8gdGhlIG5ldyBzbG90IHBvc2l0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSByZWxvY2F0ZVRhYkJhcigpOiB2b2lkIHtcbiAgICAvKipcbiAgICAgKiBgZWxgIGlzIGEgcHJvdGVjdGVkIGF0dHJpYnV0ZSBmcm9tIHRoZSBnZW5lcmF0ZWQgY29tcG9uZW50IHdyYXBwZXIuXG4gICAgICogVG8gYXZvaWQgaGF2aW5nIHRvIG1hbnVhbGx5IGNyZWF0ZSB0aGUgd3JhcHBlciBmb3IgdGFiIGJhciwgd2VcbiAgICAgKiBjYXN0IHRoZSB0YWIgYmFyIHRvIGFueSBhbmQgYWNjZXNzIHRoZSBwcm90ZWN0ZWQgYXR0cmlidXRlLlxuICAgICAqL1xuICAgIGNvbnN0IHRhYkJhciA9ICh0aGlzLnRhYkJhciBhcyBhbnkpLmVsIGFzIEhUTUxFbGVtZW50O1xuXG4gICAgaWYgKHRoaXMudGFiQmFyU2xvdCA9PT0gJ3RvcCcpIHtcbiAgICAgIC8qKlxuICAgICAgICogQSB0YWIgYmFyIHdpdGggYSBzbG90IG9mIFwidG9wXCIgc2hvdWxkIGJlIGluc2VydGVkXG4gICAgICAgKiBhdCB0aGUgdG9wIG9mIHRoZSBjb250YWluZXIuXG4gICAgICAgKi9cbiAgICAgIHRoaXMudGFic0lubmVyLm5hdGl2ZUVsZW1lbnQuYmVmb3JlKHRhYkJhcik7XG4gICAgfSBlbHNlIHtcbiAgICAgIC8qKlxuICAgICAgICogQSB0YWIgYmFyIHdpdGggYSBzbG90IG9mIFwiYm90dG9tXCIgb3Igd2l0aG91dCBhIHNsb3RcbiAgICAgICAqIHNob3VsZCBiZSBpbnNlcnRlZCBhdCB0aGUgZW5kIG9mIHRoZSBjb250YWluZXIuXG4gICAgICAgKi9cbiAgICAgIHRoaXMudGFic0lubmVyLm5hdGl2ZUVsZW1lbnQuYWZ0ZXIodGFiQmFyKTtcbiAgICB9XG4gIH1cbn1cbiJdfQ==