contextMenu.service.js 33 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358
  1. /**
  2. * @fileoverview added by tsickle
  3. * @suppress {checkTypes,constantProperty,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc
  4. */
  5. import { Overlay, ScrollStrategyOptions } from '@angular/cdk/overlay';
  6. import { ComponentPortal } from '@angular/cdk/portal';
  7. import { Injectable, ElementRef } from '@angular/core';
  8. import { Subject, Subscription } from 'rxjs';
  9. import { ContextMenuContentComponent } from './contextMenuContent.component';
  10. /**
  11. * @record
  12. */
  13. export function IContextMenuClickEvent() { }
  14. if (false) {
  15. /** @type {?|undefined} */
  16. IContextMenuClickEvent.prototype.anchorElement;
  17. /** @type {?|undefined} */
  18. IContextMenuClickEvent.prototype.contextMenu;
  19. /** @type {?|undefined} */
  20. IContextMenuClickEvent.prototype.event;
  21. /** @type {?|undefined} */
  22. IContextMenuClickEvent.prototype.parentContextMenu;
  23. /** @type {?} */
  24. IContextMenuClickEvent.prototype.item;
  25. /** @type {?|undefined} */
  26. IContextMenuClickEvent.prototype.activeMenuItemIndex;
  27. }
  28. /**
  29. * @record
  30. */
  31. export function IContextMenuContext() { }
  32. if (false) {
  33. /** @type {?} */
  34. IContextMenuContext.prototype.menuItems;
  35. /** @type {?} */
  36. IContextMenuContext.prototype.menuClass;
  37. }
  38. /**
  39. * @record
  40. */
  41. export function CloseLeafMenuEvent() { }
  42. if (false) {
  43. /** @type {?|undefined} */
  44. CloseLeafMenuEvent.prototype.exceptRootMenu;
  45. /** @type {?|undefined} */
  46. CloseLeafMenuEvent.prototype.event;
  47. }
  48. /**
  49. * @record
  50. */
  51. export function OverlayRefWithContextMenu() { }
  52. if (false) {
  53. /** @type {?|undefined} */
  54. OverlayRefWithContextMenu.prototype.contextMenu;
  55. }
  56. /**
  57. * @record
  58. */
  59. export function CancelContextMenuEvent() { }
  60. if (false) {
  61. /** @type {?} */
  62. CancelContextMenuEvent.prototype.eventType;
  63. /** @type {?|undefined} */
  64. CancelContextMenuEvent.prototype.event;
  65. }
  66. /**
  67. * @record
  68. */
  69. export function ExecuteContextMenuEvent() { }
  70. if (false) {
  71. /** @type {?} */
  72. ExecuteContextMenuEvent.prototype.eventType;
  73. /** @type {?|undefined} */
  74. ExecuteContextMenuEvent.prototype.event;
  75. /** @type {?} */
  76. ExecuteContextMenuEvent.prototype.item;
  77. /** @type {?} */
  78. ExecuteContextMenuEvent.prototype.menuItem;
  79. }
  80. export class ContextMenuService {
  81. /**
  82. * @param {?} overlay
  83. * @param {?} scrollStrategy
  84. */
  85. constructor(overlay, scrollStrategy) {
  86. this.overlay = overlay;
  87. this.scrollStrategy = scrollStrategy;
  88. this.isDestroyingLeafMenu = false;
  89. this.show = new Subject();
  90. this.triggerClose = new Subject();
  91. this.close = new Subject();
  92. this.overlays = [];
  93. this.fakeElement = {
  94. getBoundingClientRect: (/**
  95. * @return {?}
  96. */
  97. () => ({
  98. bottom: 0,
  99. height: 0,
  100. left: 0,
  101. right: 0,
  102. top: 0,
  103. width: 0,
  104. }))
  105. };
  106. }
  107. /**
  108. * @param {?} context
  109. * @return {?}
  110. */
  111. openContextMenu(context) {
  112. const { anchorElement, event, parentContextMenu } = context;
  113. if (!parentContextMenu) {
  114. /** @type {?} */
  115. const mouseEvent = (/** @type {?} */ (event));
  116. this.fakeElement.getBoundingClientRect = (/**
  117. * @return {?}
  118. */
  119. () => ({
  120. bottom: mouseEvent.clientY,
  121. height: 0,
  122. left: mouseEvent.clientX,
  123. right: mouseEvent.clientX,
  124. top: mouseEvent.clientY,
  125. width: 0,
  126. }));
  127. this.closeAllContextMenus({ eventType: 'cancel', event });
  128. /** @type {?} */
  129. const positionStrategy = this.overlay.position().connectedTo(new ElementRef(anchorElement || this.fakeElement), { originX: 'start', originY: 'bottom' }, { overlayX: 'start', overlayY: 'top' })
  130. .withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'start', overlayY: 'bottom' })
  131. .withFallbackPosition({ originX: 'end', originY: 'top' }, { overlayX: 'start', overlayY: 'top' })
  132. .withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' })
  133. .withFallbackPosition({ originX: 'end', originY: 'center' }, { overlayX: 'start', overlayY: 'center' })
  134. .withFallbackPosition({ originX: 'start', originY: 'center' }, { overlayX: 'end', overlayY: 'center' });
  135. this.overlays = [this.overlay.create({
  136. positionStrategy,
  137. panelClass: 'ngx-contextmenu',
  138. scrollStrategy: this.scrollStrategy.close(),
  139. })];
  140. this.attachContextMenu(this.overlays[0], context);
  141. }
  142. else {
  143. /** @type {?} */
  144. const positionStrategy = this.overlay.position().connectedTo(new ElementRef(event ? event.target : anchorElement), { originX: 'end', originY: 'top' }, { overlayX: 'start', overlayY: 'top' })
  145. .withFallbackPosition({ originX: 'start', originY: 'top' }, { overlayX: 'end', overlayY: 'top' })
  146. .withFallbackPosition({ originX: 'end', originY: 'bottom' }, { overlayX: 'start', overlayY: 'bottom' })
  147. .withFallbackPosition({ originX: 'start', originY: 'bottom' }, { overlayX: 'end', overlayY: 'bottom' });
  148. /** @type {?} */
  149. const newOverlay = this.overlay.create({
  150. positionStrategy,
  151. panelClass: 'ngx-contextmenu',
  152. scrollStrategy: this.scrollStrategy.close(),
  153. });
  154. this.destroySubMenus(parentContextMenu);
  155. this.overlays = this.overlays.concat(newOverlay);
  156. this.attachContextMenu(newOverlay, context);
  157. }
  158. }
  159. /**
  160. * @param {?} overlay
  161. * @param {?} context
  162. * @return {?}
  163. */
  164. attachContextMenu(overlay, context) {
  165. const { event, item, menuItems, menuClass } = context;
  166. /** @type {?} */
  167. const contextMenuContent = overlay.attach(new ComponentPortal(ContextMenuContentComponent));
  168. contextMenuContent.instance.event = event;
  169. contextMenuContent.instance.item = item;
  170. contextMenuContent.instance.menuItems = menuItems;
  171. contextMenuContent.instance.overlay = overlay;
  172. contextMenuContent.instance.isLeaf = true;
  173. contextMenuContent.instance.menuClass = menuClass;
  174. ((/** @type {?} */ (overlay))).contextMenu = contextMenuContent.instance;
  175. /** @type {?} */
  176. const subscriptions = new Subscription();
  177. subscriptions.add(contextMenuContent.instance.execute.asObservable()
  178. .subscribe((/**
  179. * @param {?} executeEvent
  180. * @return {?}
  181. */
  182. (executeEvent) => this.closeAllContextMenus(Object.assign({ eventType: 'execute' }, executeEvent)))));
  183. subscriptions.add(contextMenuContent.instance.closeAllMenus.asObservable()
  184. .subscribe((/**
  185. * @param {?} closeAllEvent
  186. * @return {?}
  187. */
  188. (closeAllEvent) => this.closeAllContextMenus(Object.assign({ eventType: 'cancel' }, closeAllEvent)))));
  189. subscriptions.add(contextMenuContent.instance.closeLeafMenu.asObservable()
  190. .subscribe((/**
  191. * @param {?} closeLeafMenuEvent
  192. * @return {?}
  193. */
  194. closeLeafMenuEvent => this.destroyLeafMenu(closeLeafMenuEvent))));
  195. subscriptions.add(contextMenuContent.instance.openSubMenu.asObservable()
  196. .subscribe((/**
  197. * @param {?} subMenuEvent
  198. * @return {?}
  199. */
  200. (subMenuEvent) => {
  201. this.destroySubMenus(contextMenuContent.instance);
  202. if (!subMenuEvent.contextMenu) {
  203. contextMenuContent.instance.isLeaf = true;
  204. return;
  205. }
  206. contextMenuContent.instance.isLeaf = false;
  207. this.show.next(subMenuEvent);
  208. })));
  209. contextMenuContent.onDestroy((/**
  210. * @return {?}
  211. */
  212. () => {
  213. menuItems.forEach((/**
  214. * @param {?} menuItem
  215. * @return {?}
  216. */
  217. menuItem => menuItem.isActive = false));
  218. subscriptions.unsubscribe();
  219. }));
  220. contextMenuContent.changeDetectorRef.detectChanges();
  221. }
  222. /**
  223. * @param {?} closeEvent
  224. * @return {?}
  225. */
  226. closeAllContextMenus(closeEvent) {
  227. if (this.overlays) {
  228. this.close.next(closeEvent);
  229. this.overlays.forEach((/**
  230. * @param {?} overlay
  231. * @param {?} index
  232. * @return {?}
  233. */
  234. (overlay, index) => {
  235. overlay.detach();
  236. overlay.dispose();
  237. }));
  238. }
  239. this.overlays = [];
  240. }
  241. /**
  242. * @return {?}
  243. */
  244. getLastAttachedOverlay() {
  245. /** @type {?} */
  246. let overlay = this.overlays[this.overlays.length - 1];
  247. while (this.overlays.length > 1 && overlay && !overlay.hasAttached()) {
  248. overlay.detach();
  249. overlay.dispose();
  250. this.overlays = this.overlays.slice(0, -1);
  251. overlay = this.overlays[this.overlays.length - 1];
  252. }
  253. return overlay;
  254. }
  255. /**
  256. * @param {?=} __0
  257. * @return {?}
  258. */
  259. destroyLeafMenu({ exceptRootMenu, event } = {}) {
  260. if (this.isDestroyingLeafMenu) {
  261. return;
  262. }
  263. this.isDestroyingLeafMenu = true;
  264. setTimeout((/**
  265. * @return {?}
  266. */
  267. () => {
  268. /** @type {?} */
  269. const overlay = this.getLastAttachedOverlay();
  270. if (this.overlays.length > 1 && overlay) {
  271. overlay.detach();
  272. overlay.dispose();
  273. }
  274. if (!exceptRootMenu && this.overlays.length > 0 && overlay) {
  275. this.close.next({ eventType: 'cancel', event });
  276. overlay.detach();
  277. overlay.dispose();
  278. }
  279. /** @type {?} */
  280. const newLeaf = this.getLastAttachedOverlay();
  281. if (newLeaf) {
  282. newLeaf.contextMenu.isLeaf = true;
  283. }
  284. this.isDestroyingLeafMenu = false;
  285. }));
  286. }
  287. /**
  288. * @param {?} contextMenu
  289. * @return {?}
  290. */
  291. destroySubMenus(contextMenu) {
  292. /** @type {?} */
  293. const overlay = contextMenu.overlay;
  294. /** @type {?} */
  295. const index = this.overlays.indexOf(overlay);
  296. this.overlays.slice(index + 1).forEach((/**
  297. * @param {?} subMenuOverlay
  298. * @return {?}
  299. */
  300. subMenuOverlay => {
  301. subMenuOverlay.detach();
  302. subMenuOverlay.dispose();
  303. }));
  304. }
  305. /**
  306. * @param {?} contextMenuContent
  307. * @return {?}
  308. */
  309. isLeafMenu(contextMenuContent) {
  310. /** @type {?} */
  311. const overlay = this.getLastAttachedOverlay();
  312. return contextMenuContent.overlay === overlay;
  313. }
  314. }
  315. ContextMenuService.decorators = [
  316. { type: Injectable }
  317. ];
  318. /** @nocollapse */
  319. ContextMenuService.ctorParameters = () => [
  320. { type: Overlay },
  321. { type: ScrollStrategyOptions }
  322. ];
  323. if (false) {
  324. /** @type {?} */
  325. ContextMenuService.prototype.isDestroyingLeafMenu;
  326. /** @type {?} */
  327. ContextMenuService.prototype.show;
  328. /** @type {?} */
  329. ContextMenuService.prototype.triggerClose;
  330. /** @type {?} */
  331. ContextMenuService.prototype.close;
  332. /**
  333. * @type {?}
  334. * @private
  335. */
  336. ContextMenuService.prototype.contextMenuContent;
  337. /**
  338. * @type {?}
  339. * @private
  340. */
  341. ContextMenuService.prototype.overlays;
  342. /**
  343. * @type {?}
  344. * @private
  345. */
  346. ContextMenuService.prototype.fakeElement;
  347. /**
  348. * @type {?}
  349. * @private
  350. */
  351. ContextMenuService.prototype.overlay;
  352. /**
  353. * @type {?}
  354. * @private
  355. */
  356. ContextMenuService.prototype.scrollStrategy;
  357. }
  358. //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29udGV4dE1lbnUuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiJuZzovL25neC1jb250ZXh0bWVudS8iLCJzb3VyY2VzIjpbImxpYi9jb250ZXh0TWVudS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiI7Ozs7QUFBQSxPQUFPLEVBQUUsT0FBTyxFQUFjLHFCQUFxQixFQUFFLE1BQU0sc0JBQXNCLENBQUM7QUFDbEYsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFCQUFxQixDQUFDO0FBQ3RELE9BQU8sRUFBZ0IsVUFBVSxFQUFFLFVBQVUsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUNyRSxPQUFPLEVBQUUsT0FBTyxFQUFFLFlBQVksRUFBRSxNQUFNLE1BQU0sQ0FBQztBQUk3QyxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7OztBQUU3RSw0Q0FPQzs7O0lBTkMsK0NBQXNDOztJQUN0Qyw2Q0FBbUM7O0lBQ25DLHVDQUFtQzs7SUFDbkMsbURBQWdEOztJQUNoRCxzQ0FBVTs7SUFDVixxREFBNkI7Ozs7O0FBRS9CLHlDQUdDOzs7SUFGQyx3Q0FBc0M7O0lBQ3RDLHdDQUFrQjs7Ozs7QUFFcEIsd0NBR0M7OztJQUZDLDRDQUF5Qjs7SUFDekIsbUNBQW1DOzs7OztBQUVyQywrQ0FFQzs7O0lBREMsZ0RBQTBDOzs7OztBQUc1Qyw0Q0FHQzs7O0lBRkMsMkNBQW9COztJQUNwQix1Q0FBbUM7Ozs7O0FBRXJDLDZDQUtDOzs7SUFKQyw0Q0FBcUI7O0lBQ3JCLHdDQUFtQzs7SUFDbkMsdUNBQVU7O0lBQ1YsMkNBQW1DOztBQUtyQyxNQUFNLE9BQU8sa0JBQWtCOzs7OztJQW9CN0IsWUFDVSxPQUFnQixFQUNoQixjQUFxQztRQURyQyxZQUFPLEdBQVAsT0FBTyxDQUFTO1FBQ2hCLG1CQUFjLEdBQWQsY0FBYyxDQUF1QjtRQXJCeEMseUJBQW9CLEdBQUcsS0FBSyxDQUFDO1FBRTdCLFNBQUksR0FBb0MsSUFBSSxPQUFPLEVBQTBCLENB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Ozs7SUFFTSxVQUFVLENBQUMsa0JBQStDOztjQUN6RCxPQUFPLEdBQUcsSUFBSSxDQUFDLHNCQUFzQixFQUFFO1FBQzdDLE9BQU8sa0JBQWtCLENBQUMsT0FBTyxLQUFLLE9BQU8sQ0FBQztJQUNoRCxDQUFDOzs7WUE3TEYsVUFBVTs7OztZQXpDRixPQUFPO1lBQWMscUJBQXFCOzs7O0lBMkNqRCxrREFBb0M7O0lBRXBDLGtDQUFxRjs7SUFDckYsMENBQTBFOztJQUMxRSxtQ0FBNkQ7Ozs7O0lBRTdELGdEQUFzRTs7Ozs7SUFDdEUsc0NBQW9DOzs7OztJQUNwQyx5Q0FTRTs7Ozs7SUFHQSxxQ0FBd0I7Ozs7O0lBQ3hCLDRDQUE2QyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IE92ZXJsYXksIE92ZXJsYXlSZWYsIFNjcm9sbFN0cmF0ZWd5T3B0aW9ucyB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9vdmVybGF5JztcbmltcG9ydCB7IENvbXBvbmVudFBvcnRhbCB9IGZyb20gJ0Bhbmd1bGFyL2Nkay9wb3J0YWwnO1xuaW1wb3J0IHsgQ29tcG9uZW50UmVmLCBJbmplY3RhYmxlLCBFbGVtZW50UmVmIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJqZWN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcblxuaW1wb3J0IHsgQ29udGV4dE1lbnVDb21wb25lbnQgfSBmcm9tICcuL2NvbnRleHRNZW51LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmUgfSBmcm9tICcuL2NvbnRleHRNZW51Lml0ZW0uZGlyZWN0aXZlJztcbmltcG9ydCB7IENvbnRleHRNZW51Q29udGVudENvbXBvbmVudCB9IGZyb20gJy4vY29udGV4dE1lbnVDb250ZW50LmNvbXBvbmVudCc7XG5cbmV4cG9ydCBpbnRlcmZhY2UgSUNvbnRleHRNZW51Q2xpY2tFdmVudCB7XG4gIGFuY2hvckVsZW1lbnQ/OiBFbGVtZW50IHwgRXZlbnRUYXJnZXQ7XG4gIGNvbnRleHRNZW51PzogQ29udGV4dE1lbnVDb21wb25lbnQ7XG4gIGV2ZW50PzogTW91c2VFdmVudCB8IEtleWJvYXJkRXZlbnQ7XG4gIHBhcmVudENvbnRleHRNZW51PzogQ29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50O1xuICBpdGVtOiBhbnk7XG4gIGFjdGl2ZU1lbnVJdGVtSW5kZXg/OiBudW1iZXI7XG59XG5leHBvcnQgaW50ZXJmYWNlIElDb250ZXh0TWVudUNvbnRleHQgZXh0ZW5kcyBJQ29udGV4dE1lbnVDbGlja0V2ZW50IHtcbiAgbWVudUl0ZW1zOiBDb250ZXh0TWVudUl0ZW1EaXJlY3RpdmVbXTtcbiAgbWVudUNsYXNzOiBzdHJpbmc7XG59XG5leHBvcnQgaW50ZXJmYWNlIENsb3NlTGVhZk1lbnVFdmVudCB7XG4gIGV4Y2VwdFJvb3RNZW51PzogYm9vbGVhbjtcbiAgZXZlbnQ/OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgT3ZlcmxheVJlZldpdGhDb250ZXh0TWVudSBleHRlbmRzIE92ZXJsYXlSZWYge1xuICBjb250ZXh0TWVudT86IENvbnRleHRNZW51Q29udGVudENvbXBvbmVudDtcbn1cblxuZXhwb3J0IGludGVyZmFjZSBDYW5jZWxDb250ZXh0TWVudUV2ZW50IHtcbiAgZXZlbnRUeXBlOiAnY2FuY2VsJztcbiAgZXZlbnQ/OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbn1cbmV4cG9ydCBpbnRlcmZhY2UgRXhlY3V0ZUNvbnRleHRNZW51RXZlbnQge1xuICBldmVudFR5cGU6ICdleGVjdXRlJztcbiAgZXZlbnQ/OiBNb3VzZUV2ZW50IHwgS2V5Ym9hcmRFdmVudDtcbiAgaXRlbTogYW55O1xuICBtZW51SXRlbTogQ29udGV4dE1lbnVJdGVtRGlyZWN0aXZlO1xufVxuZXhwb3J0IHR5cGUgQ2xvc2VDb250ZXh0TWVudUV2ZW50ID0gRXhlY3V0ZUNvbnRleHRNZW51RXZlbnQgfCBDYW5jZWxDb250ZXh0TWVudUV2ZW50O1xuXG5ASW5qZWN0YWJsZSgpXG5leHBvcnQgY2xhc3MgQ29udGV4dE1lbnVTZXJ2aWNlIHtcbiAgcHVibGljIGlzRGVzdHJveWluZ0xlYWZNZW51ID0gZmFsc2U7XG5cbiAgcHVibGljIHNob3c6IFN1YmplY3Q8SUNvbnRleHRNZW51Q2xpY2tFdmVudD4gPSBuZXcgU3ViamVjdDxJQ29udGV4dE1lbnVDbGlja0V2ZW50PigpO1xuICBwdWJsaWMgdHJpZ2dlckNsb3NlOiBTdWJqZWN0PENvbnRleHRNZW51Q29udGVudENvbXBvbmVudD4gPSBuZXcgU3ViamVjdCgpO1xuICBwdWJsaWMgY2xvc2U6IFN1YmplY3Q8Q2xvc2VDb250ZXh0TWVudUV2ZW50PiA9IG5ldyBTdWJqZWN0KCk7XG5cbiAgcHJpdmF0ZSBjb250ZXh0TWVudUNvbnRlbnQ6IENvbXBvbmVudFJlZjxDb250ZXh0TWVudUNvbnRlbnRDb21wb25lbnQ+O1xuICBwcml2YXRlIG92ZXJsYXlzOiBPdmVybGF5UmVmW10gPSBbXTtcbiAgcHJpdmF0ZSBmYWtlRWxlbWVudDogYW55ID0ge1xuICAgIGdldEJvdW5kaW5nQ2xpZW50UmVjdDogKCk6IENsaWVudFJlY3QgPT4gKHtcbiAgICAgIGJvdHRvbTogMCxcbiAgICAgIGhlaWdodDogMCxcbiAgICAgIGxlZnQ6IDAsXG4gICAgICByaWdodDogMCxcbiAgICAgIHRvcDogMCxcbiAgICAgIHdpZHRoOiAwLFxuICAgIH0pXG4gIH07XG5cbiAgY29uc3RydWN0b3IoXG4gICAgcHJpdmF0ZSBvdmVybGF5OiBPdmVybGF5LFxuICAgIHByaXZhdGUgc2Nyb2xsU3RyYXRlZ3k6IFNjcm9sbFN0cmF0ZWd5T3B0aW9ucyxcbiAgKSB7IH1cblxuICBwdWJsaWMgb3BlbkNvbnRleHRNZW51KGNvbnRleHQ6IElDb250ZXh0TWVudUNvbnRleHQpIHtcbiAgICBjb25zdCB7IGFuY2hvckVsZW1lbnQsIGV2ZW50LCBwYXJlbnRDb250ZXh0TWVudSB9ID0gY29udGV4dDtcblxuICAgIGlmICghcGFyZW50Q29udGV4dE1lbnUpIHtcbiAgICAgIGNvbnN0IG1vdXNlRXZlbnQgPSBldmVudCBhcyBNb3VzZUV2ZW50O1xuICAgICAgdGhpcy5mYWtlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QgPSAoKTogQ2xpZW50UmVjdCA9PiAoe1xuICAgICAgICBib3R0b206IG1vdXNlRXZlbnQuY2xpZW50WSxcbiAgICAgICAgaGVpZ2h0OiAwLFxuICAgICAgICBsZWZ0OiBtb3VzZUV2ZW50LmNsaWVudFgsXG4gICAgICAgIHJpZ2h0OiBtb3VzZUV2ZW50LmNsaWVudFgsXG4gICAgICAgIHRvcDogbW91c2VFdmVudC5jbGllbnRZLFxuICAgICAgICB3aWR0aDogMCxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5jbG9zZUFsbENvbnRleHRNZW51cyh7IGV2ZW50VHlwZTogJ2NhbmNlbCcsIGV2ZW50IH0pO1xuICAgICAgY29uc3QgcG9zaXRpb25TdHJhdGVneSA9IHRoaXMub3ZlcmxheS5wb3NpdGlvbigpLmNvbm5lY3RlZFRvKFxuICAgICAgICBuZXcgRWxlbWVudFJlZihhbmNob3JFbGVtZW50IHx8IHRoaXMuZmFrZUVsZW1lbnQpLFxuICAgICAgICB7IG9yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICdib3R0b20nIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdzdGFydCcsIG92ZXJsYXlZOiAndG9wJyB9KVxuICAgICAgICAud2l0aEZhbGxiYWNrUG9zaXRpb24oXG4gICAgICAgIHsgb3JpZ2luWDogJ3N0YXJ0Jywgb3JpZ2luWTogJ3RvcCcgfSxcbiAgICAgICAgeyBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICdib3R0b20nIH0pXG4gICAgICAgIC53aXRoRmFsbGJhY2tQb3NpdGlvbihcbiAgICAgICAgeyBvcmlnaW5YOiAnZW5kJywgb3JpZ2luWTogJ3RvcCcgfSxcbiAgICAgICAgeyBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICd0b3AnIH0pXG4gICAgICAgIC53aXRoRmFsbGJhY2tQb3NpdGlvbihcbiAgICAgICAgeyBvcmlnaW5YOiAnc3RhcnQnLCBvcmlnaW5ZOiAndG9wJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnZW5kJywgb3ZlcmxheVk6ICd0b3AnIH0pXG4gICAgICAgIC53aXRoRmFsbGJhY2tQb3NpdGlvbihcbiAgICAgICAgeyBvcmlnaW5YOiAnZW5kJywgb3JpZ2luWTogJ2NlbnRlcicgfSxcbiAgICAgICAgeyBvdmVybGF5WDogJ3N0YXJ0Jywgb3ZlcmxheVk6ICdjZW50ZXInIH0pXG4gICAgICAgIC53aXRoRmFsbGJhY2tQb3NpdGlvbihcbiAgICAgICAgeyBvcmlnaW5YOiAnc3RhcnQnLCBvcmlnaW5ZOiAnY2VudGVyJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnZW5kJywgb3ZlcmxheVk6ICdjZW50ZXInIH0pXG4gICAgICAgIDtcbiAgICAgIHRoaXMub3ZlcmxheXMgPSBbdGhpcy5vdmVybGF5LmNyZWF0ZSh7XG4gICAgICAgIHBvc2l0aW9uU3RyYXRlZ3ksXG4gICAgICAgIHBhbmVsQ2xhc3M6ICduZ3gtY29udGV4dG1lbnUnLFxuICAgICAgICBzY3JvbGxTdHJhdGVneTogdGhpcy5zY3JvbGxTdHJhdGVneS5jbG9zZSgpLFxuICAgICAgfSldO1xuICAgICAgdGhpcy5hdHRhY2hDb250ZXh0TWVudSh0aGlzLm92ZXJsYXlzWzBdLCBjb250ZXh0KTtcbiAgICB9IGVsc2Uge1xuICAgICAgY29uc3QgcG9zaXRpb25TdHJhdGVneSA9IHRoaXMub3ZlcmxheS5wb3NpdGlvbigpLmNvbm5lY3RlZFRvKFxuICAgICAgICBuZXcgRWxlbWVudFJlZihldmVudCA/IGV2ZW50LnRhcmdldCA6IGFuY2hvckVsZW1lbnQpLFxuICAgICAgICB7IG9yaWdpblg6ICdlbmQnLCBvcmlnaW5ZOiAndG9wJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ3RvcCcgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICd0b3AnIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdlbmQnLCBvdmVybGF5WTogJ3RvcCcgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdlbmQnLCBvcmlnaW5ZOiAnYm90dG9tJyB9LFxuICAgICAgICB7IG92ZXJsYXlYOiAnc3RhcnQnLCBvdmVybGF5WTogJ2JvdHRvbScgfSlcbiAgICAgICAgLndpdGhGYWxsYmFja1Bvc2l0aW9uKFxuICAgICAgICB7IG9yaWdpblg6ICdzdGFydCcsIG9yaWdpblk6ICdib3R0b20nIH0sXG4gICAgICAgIHsgb3ZlcmxheVg6ICdlbmQnLCBvdmVybGF5WTogJ2JvdHRvbScgfSlcbiAgICAgICAgO1xuICAgICAgY29uc3QgbmV3T3ZlcmxheSA9IHRoaXMub3ZlcmxheS5jcmVhdGUoe1xuICAgICAgICBwb3NpdGlvblN0cmF0ZWd5LFxuICAgICAgICBwYW5lbENsYXNzOiAnbmd4LWNvbnRleHRtZW51JyxcbiAgICAgICAgc2Nyb2xsU3RyYXRlZ3k6IHRoaXMuc2Nyb2xsU3RyYXRlZ3kuY2xvc2UoKSxcbiAgICAgIH0pO1xuICAgICAgdGhpcy5kZXN0cm95U3ViTWVudXMocGFyZW50Q29udGV4dE1lbnUpO1xuICAgICAgdGhpcy5vdmVybGF5cyA9IHRoaXMub3ZlcmxheXMuY29uY2F0KG5ld092ZXJsYXkpO1xuICAgICAgdGhpcy5hdHRhY2hDb250ZXh0TWVudShuZXdPdmVybGF5LCBjb250ZXh0KTtcbiAgICB9XG4gIH1cblxuICBwdWJsaWMgYXR0YWNoQ29udGV4dE1lbnUob3ZlcmxheTogT3ZlcmxheVJlZiwgY29udGV4dDogSUNvbnRleHRNZW51Q29udGV4dCk6IHZvaWQge1xuICAgIGNvbnN0IHsgZXZlbnQsIGl0ZW0sIG1lbnVJdGVtcywgbWVudUNsYXNzIH0gPSBjb250ZXh0O1xuXG4gICAgY29uc3QgY29udGV4dE1lbnVDb250ZW50OiBDb21wb25lbnRSZWY8Q29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50PiA9IG92ZXJsYXkuYXR0YWNoKG5ldyBDb21wb25lbnRQb3J0YWwoQ29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50KSk7XG4gICAgY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLmV2ZW50ID0gZXZlbnQ7XG4gICAgY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLml0ZW0gPSBpdGVtO1xuICAgIGNvbnRleHRNZW51Q29udGVudC5pbnN0YW5jZS5tZW51SXRlbXMgPSBtZW51SXRlbXM7XG4gICAgY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLm92ZXJsYXkgPSBvdmVybGF5O1xuICAgIGNvbnRleHRNZW51Q29udGVudC5pbnN0YW5jZS5pc0xlYWYgPSB0cnVlO1xuICAgIGNvbnRleHRNZW51Q29udGVudC5pbnN0YW5jZS5tZW51Q2xhc3MgPSBtZW51Q2xhc3M7XG4gICAgKDxPdmVybGF5UmVmV2l0aENvbnRleHRNZW51Pm92ZXJsYXkpLmNvbnRleHRNZW51ID0gY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlO1xuXG4gICAgY29uc3Qgc3Vic2NyaXB0aW9uczogU3Vic2NyaXB0aW9uID0gbmV3IFN1YnNjcmlwdGlvbigpO1xuICAgIHN1YnNjcmlwdGlvbnMuYWRkKGNvbnRleHRNZW51Q29udGVudC5pbnN0YW5jZS5leGVjdXRlLmFzT2JzZXJ2YWJsZSgpXG4gICAgICAuc3Vic2NyaWJlKChleGVjdXRlRXZlbnQpID0+IHRoaXMuY2xvc2VBbGxDb250ZXh0TWVudXMoeyBldmVudFR5cGU6ICdleGVjdXRlJywgLi4uZXhlY3V0ZUV2ZW50IH0pKSk7XG4gICAgc3Vic2NyaXB0aW9ucy5hZGQoY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLmNsb3NlQWxsTWVudXMuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5zdWJzY3JpYmUoKGNsb3NlQWxsRXZlbnQpID0+IHRoaXMuY2xvc2VBbGxDb250ZXh0TWVudXMoeyBldmVudFR5cGU6ICdjYW5jZWwnLCAuLi5jbG9zZUFsbEV2ZW50IH0pKSk7XG4gICAgc3Vic2NyaXB0aW9ucy5hZGQoY29udGV4dE1lbnVDb250ZW50Lmluc3RhbmNlLmNsb3NlTGVhZk1lbnUuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5zdWJzY3JpYmUoY2xvc2VMZWFmTWVudUV2ZW50ID0+IHRoaXMuZGVzdHJveUxlYWZNZW51KGNsb3NlTGVhZk1lbnVFdmVudCkpKTtcbiAgICBzdWJzY3JpcHRpb25zLmFkZChjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2Uub3BlblN1Yk1lbnUuYXNPYnNlcnZhYmxlKClcbiAgICAgIC5zdWJzY3JpYmUoKHN1Yk1lbnVFdmVudDogSUNvbnRleHRNZW51Q29udGV4dCkgPT4ge1xuICAgICAgICB0aGlzLmRlc3Ryb3lTdWJNZW51cyhjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2UpO1xuICAgICAgICBpZiAoIXN1Yk1lbnVFdmVudC5jb250ZXh0TWVudSkge1xuICAgICAgICAgIGNvbnRleHRNZW51Q29udGVudC5pbnN0YW5jZS5pc0xlYWYgPSB0cnVlO1xuICAgICAgICAgIHJldHVybjtcbiAgICAgICAgfVxuICAgICAgICBjb250ZXh0TWVudUNvbnRlbnQuaW5zdGFuY2UuaXNMZWFmID0gZmFsc2U7XG4gICAgICAgIHRoaXMuc2hvdy5uZXh0KHN1Yk1lbnVFdmVudCk7XG4gICAgICB9KSk7XG4gICAgY29udGV4dE1lbnVDb250ZW50Lm9uRGVzdHJveSgoKSA9PiB7XG4gICAgICBtZW51SXRlbXMuZm9yRWFjaChtZW51SXRlbSA9PiBtZW51SXRlbS5pc0FjdGl2ZSA9IGZhbHNlKTtcbiAgICAgIHN1YnNjcmlwdGlvbnMudW5zdWJzY3JpYmUoKTtcbiAgICB9KTtcbiAgICBjb250ZXh0TWVudUNvbnRlbnQuY2hhbmdlRGV0ZWN0b3JSZWYuZGV0ZWN0Q2hhbmdlcygpO1xuICB9XG5cbiAgcHVibGljIGNsb3NlQWxsQ29udGV4dE1lbnVzKGNsb3NlRXZlbnQ6IENsb3NlQ29udGV4dE1lbnVFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLm92ZXJsYXlzKSB7XG4gICAgICB0aGlzLmNsb3NlLm5leHQoY2xvc2VFdmVudCk7XG4gICAgICB0aGlzLm92ZXJsYXlzLmZvckVhY2goKG92ZXJsYXksIGluZGV4KSA9PiB7XG4gICAgICAgIG92ZXJsYXkuZGV0YWNoKCk7XG4gICAgICAgIG92ZXJsYXkuZGlzcG9zZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICAgIHRoaXMub3ZlcmxheXMgPSBbXTtcbiAgfVxuXG4gIHB1YmxpYyBnZXRMYXN0QXR0YWNoZWRPdmVybGF5KCk6IE92ZXJsYXlSZWZXaXRoQ29udGV4dE1lbnUge1xuICAgIGxldCBvdmVybGF5OiBPdmVybGF5UmVmID0gdGhpcy5vdmVybGF5c1t0aGlzLm92ZXJsYXlzLmxlbmd0aCAtIDFdO1xuICAgIHdoaWxlICh0aGlzLm92ZXJsYXlzLmxlbmd0aCA+IDEgJiYgb3ZlcmxheSAmJiAhb3ZlcmxheS5oYXNBdHRhY2hlZCgpKSB7XG4gICAgICBvdmVybGF5LmRldGFjaCgpO1xuICAgICAgb3ZlcmxheS5kaXNwb3NlKCk7XG4gICAgICB0aGlzLm92ZXJsYXlzID0gdGhpcy5vdmVybGF5cy5zbGljZSgwLCAtMSk7XG4gICAgICBvdmVybGF5ID0gdGhpcy5vdmVybGF5c1t0aGlzLm92ZXJsYXlzLmxlbmd0aCAtIDFdO1xuICAgIH1cbiAgICByZXR1cm4gb3ZlcmxheTtcbiAgfVxuXG4gIHB1YmxpYyBkZXN0cm95TGVhZk1lbnUoeyBleGNlcHRSb290TWVudSwgZXZlbnQgfTogQ2xvc2VMZWFmTWVudUV2ZW50ID0ge30pOiB2b2lkIHtcbiAgICBpZiAodGhpcy5pc0Rlc3Ryb3lpbmdMZWFmTWVudSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cbiAgICB0aGlzLmlzRGVzdHJveWluZ0xlYWZNZW51ID0gdHJ1ZTtcblxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgY29uc3Qgb3ZlcmxheSA9IHRoaXMuZ2V0TGFzdEF0dGFjaGVkT3ZlcmxheSgpO1xuICAgICAgaWYgKHRoaXMub3ZlcmxheXMubGVuZ3RoID4gMSAmJiBvdmVybGF5KSB7XG4gICAgICAgIG92ZXJsYXkuZGV0YWNoKCk7XG4gICAgICAgIG92ZXJsYXkuZGlzcG9zZSgpO1xuICAgICAgfVxuICAgICAgaWYgKCFleGNlcHRSb290TWVudSAmJiB0aGlzLm92ZXJsYXlzLmxlbmd0aCA+IDAgJiYgb3ZlcmxheSkge1xuICAgICAgICB0aGlzLmNsb3NlLm5leHQoeyBldmVudFR5cGU6ICdjYW5jZWwnLCBldmVudCB9KTtcbiAgICAgICAgb3ZlcmxheS5kZXRhY2goKTtcbiAgICAgICAgb3ZlcmxheS5kaXNwb3NlKCk7XG4gICAgICB9XG5cbiAgICAgIGNvbnN0IG5ld0xlYWYgPSB0aGlzLmdldExhc3RBdHRhY2hlZE92ZXJsYXkoKTtcbiAgICAgIGlmIChuZXdMZWFmKSB7XG4gICAgICAgIG5ld0xlYWYuY29udGV4dE1lbnUuaXNMZWFmID0gdHJ1ZTtcbiAgICAgIH1cblxuICAgICAgdGhpcy5pc0Rlc3Ryb3lpbmdMZWFmTWVudSA9IGZhbHNlO1xuICAgIH0pO1xuICB9XG5cbiAgcHVibGljIGRlc3Ryb3lTdWJNZW51cyhjb250ZXh0TWVudTogQ29udGV4dE1lbnVDb250ZW50Q29tcG9uZW50KTogdm9pZCB7XG4gICAgY29uc3Qgb3ZlcmxheSA9IGNvbnRleHRNZW51Lm92ZXJsYXk7XG4gICAgY29uc3QgaW5kZXggPSB0aGlzLm92ZXJsYXlzLmluZGV4T2Yob3ZlcmxheSk7XG4gICAgdGhpcy5vdmVybGF5cy5zbGljZShpbmRleCArIDEpLmZvckVhY2goc3ViTWVudU92ZXJsYXkgPT4ge1xuICAgICAgc3ViTWVudU92ZXJsYXkuZGV0YWNoKCk7XG4gICAgICBzdWJNZW51T3ZlcmxheS5kaXNwb3NlKCk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgaXNMZWFmTWVudShjb250ZXh0TWVudUNvbnRlbnQ6IENvbnRleHRNZW51Q29udGVudENvbXBvbmVudCk6IGJvb2xlYW4ge1xuICAgIGNvbnN0IG92ZXJsYXkgPSB0aGlzLmdldExhc3RBdHRhY2hlZE92ZXJsYXkoKTtcbiAgICByZXR1cm4gY29udGV4dE1lbnVDb250ZW50Lm92ZXJsYXkgPT09IG92ZXJsYXk7XG4gIH1cbn1cbiJdfQ==