@scion/workbench 18.0.0-beta.1 → 18.0.0-beta.10

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.
Files changed (275) hide show
  1. package/_index.scss +7 -5
  2. package/design/_workbench-global-styles.scss +18 -0
  3. package/design/_workbench-icon-font.scss +1 -1
  4. package/design/_workbench-popup-global-styles.scss +1 -1
  5. package/design/{_workbench-view-drag-image-global-styles.scss → _workbench-view-global-styles.scss} +1 -2
  6. package/esm2022/lib/common/class-list.mjs +67 -29
  7. package/esm2022/lib/common/math.util.mjs +16 -0
  8. package/esm2022/lib/common/objects.util.mjs +7 -1
  9. package/esm2022/lib/common/operators.mjs +1 -12
  10. package/esm2022/lib/common/uid.util.mjs +22 -0
  11. package/esm2022/lib/content-projection/content-as-overlay.component.mjs +85 -28
  12. package/esm2022/lib/content-projection/workbench-element-references.mjs +32 -0
  13. package/esm2022/lib/dialog/dialog-header/dialog-header.component.mjs +3 -8
  14. package/esm2022/lib/dialog/movable.directive.mjs +3 -3
  15. package/esm2022/lib/dialog/resizable.directive.mjs +3 -3
  16. package/esm2022/lib/dialog/workbench-dialog.component.mjs +25 -23
  17. package/esm2022/lib/dialog/workbench-dialog.mjs +61 -1
  18. package/esm2022/lib/dialog//311/265workbench-dialog.mjs +98 -60
  19. package/esm2022/lib/dialog//311/265workbench-dialog.service.mjs +26 -23
  20. package/esm2022/lib/executor/latest-task-executor.mjs +55 -0
  21. package/esm2022/lib/executor/single-task-executor.mjs +9 -19
  22. package/esm2022/lib/filter-field/filter-field.component.mjs +5 -5
  23. package/esm2022/lib/layout/grid-element/grid-element.component.mjs +8 -18
  24. package/esm2022/lib/layout/main-area-layout/main-area-layout.component.mjs +18 -21
  25. package/esm2022/lib/layout/migration/model/workbench-layout-migration-v5.model.mjs +11 -0
  26. package/esm2022/lib/layout/migration/model/workbench-layout-migration-v6.model.mjs +11 -0
  27. package/esm2022/lib/layout/migration/workbench-layout-migration-v3.service.mjs +4 -4
  28. package/esm2022/lib/layout/migration/workbench-layout-migration-v5.service.mjs +67 -0
  29. package/esm2022/lib/layout/migration/workbench-layout-migration-v6.service.mjs +59 -0
  30. package/esm2022/lib/layout/stringifier.mjs +70 -0
  31. package/esm2022/lib/layout/workbench-layout.component.mjs +18 -22
  32. package/esm2022/lib/layout/workbench-layout.mjs +1 -1
  33. package/esm2022/lib/layout/workbench-layout.model.mjs +1 -1
  34. package/esm2022/lib/layout/workbench-layout.service.mjs +26 -24
  35. package/esm2022/lib/layout/workbench-layouts.util.mjs +1 -9
  36. package/esm2022/lib/layout/workench-layout-serializer.service.mjs +19 -27
  37. package/esm2022/lib/layout//311/265workbench-layout.factory.mjs +3 -2
  38. package/esm2022/lib/layout//311/265workbench-layout.mjs +73 -62
  39. package/esm2022/lib/logging/logging-support.mjs +7 -13
  40. package/esm2022/lib/logging//311/265logger.mjs +10 -10
  41. package/esm2022/lib/message-box/message-box-footer/message-box-footer.component.mjs +7 -6
  42. package/esm2022/lib/message-box/message-box-header/message-box-header.component.mjs +3 -3
  43. package/esm2022/lib/message-box/workbench-message-box.component.mjs +2 -2
  44. package/esm2022/lib/message-box//311/265workbench-message-box.service.mjs +3 -2
  45. package/esm2022/lib/microfrontend-platform/common/microfrontend.util.mjs +22 -6
  46. package/esm2022/lib/microfrontend-platform/initialization/microfrontend-platform-initializer.service.mjs +28 -21
  47. package/esm2022/lib/microfrontend-platform/initialization/ng-zone-observable-decorator.mjs +3 -3
  48. package/esm2022/lib/microfrontend-platform/initialization/workbench-host-manifest-interceptor.service.mjs +11 -1
  49. package/esm2022/lib/microfrontend-platform/manifest-object-cache.service.mjs +63 -0
  50. package/esm2022/lib/microfrontend-platform/microfrontend-dialog/microfrontend-dialog-capability-validator.interceptor.mjs +5 -4
  51. package/esm2022/lib/microfrontend-platform/microfrontend-dialog/microfrontend-dialog.component.mjs +6 -10
  52. package/esm2022/lib/microfrontend-platform/microfrontend-host-dialog/microfrontend-host-dialog.component.mjs +18 -9
  53. package/esm2022/lib/microfrontend-platform/microfrontend-host-message-box/microfrontend-host-message-box.component.mjs +7 -6
  54. package/esm2022/lib/microfrontend-platform/microfrontend-host-message-box/text-message/text-message.component.mjs +3 -3
  55. package/esm2022/lib/microfrontend-platform/microfrontend-host-popup/microfrontend-host-popup.component.mjs +15 -13
  56. package/esm2022/lib/microfrontend-platform/microfrontend-message-box/microfrontend-message-box-capability-validator.interceptor.mjs +3 -2
  57. package/esm2022/lib/microfrontend-platform/microfrontend-message-box/microfrontend-message-box.component.mjs +6 -11
  58. package/esm2022/lib/microfrontend-platform/microfrontend-perspective/microfrontend-perspective-capability-validator.interceptor.mjs +39 -0
  59. package/esm2022/lib/microfrontend-platform/microfrontend-perspective/microfrontend-perspective-installer.service.mjs +120 -0
  60. package/esm2022/lib/microfrontend-platform/microfrontend-perspective/microfrontend-perspective-intent-handler.interceptor.mjs +55 -0
  61. package/esm2022/lib/microfrontend-platform/microfrontend-perspective/workbench-perspective-data.mjs +19 -0
  62. package/esm2022/lib/microfrontend-platform/microfrontend-popup/microfrontend-popup-capability-validator.interceptor.mjs +4 -3
  63. package/esm2022/lib/microfrontend-platform/microfrontend-popup/microfrontend-popup-intent-handler.interceptor.mjs +11 -12
  64. package/esm2022/lib/microfrontend-platform/microfrontend-popup/microfrontend-popup.component.mjs +12 -28
  65. package/esm2022/lib/microfrontend-platform/microfrontend-splash/microfrontend-splash.component.mjs +3 -3
  66. package/esm2022/lib/microfrontend-platform/microfrontend-view/microfrontend-view-command-handler.service.mjs +11 -27
  67. package/esm2022/lib/microfrontend-platform/microfrontend-view/microfrontend-view.component.mjs +91 -71
  68. package/esm2022/lib/microfrontend-platform/public_api.mjs +2 -1
  69. package/esm2022/lib/microfrontend-platform/routing/microfrontend-view-capability-validator.interceptor.mjs +5 -4
  70. package/esm2022/lib/microfrontend-platform/routing/microfrontend-view-intent-handler.interceptor.mjs +18 -16
  71. package/esm2022/lib/microfrontend-platform/routing/microfrontend-view-routes.mjs +30 -8
  72. package/esm2022/lib/microfrontend-platform/stable-capability-id-assigner.interceptor.mjs +32 -0
  73. package/esm2022/lib/microfrontend-platform/workbench-microfrontend-support.mjs +26 -8
  74. package/esm2022/lib/notification/notification-list.component.mjs +4 -8
  75. package/esm2022/lib/notification/notification.component.mjs +4 -5
  76. package/esm2022/lib/notification/notification.service.mjs +5 -4
  77. package/esm2022/lib/page-not-found/page-not-found.component.mjs +5 -7
  78. package/esm2022/lib/part/part-action-bar/part-action-bar.component.mjs +11 -19
  79. package/esm2022/lib/part/part-action-bar/part-action.directive.mjs +4 -4
  80. package/esm2022/lib/part/part-bar/part-bar.component.mjs +333 -264
  81. package/esm2022/lib/part/part-portal.pipe.mjs +8 -8
  82. package/esm2022/lib/part/part.component.mjs +33 -42
  83. package/esm2022/lib/part/view-context-menu/text.component.mjs +16 -12
  84. package/esm2022/lib/part/view-context-menu/view-menu.component.mjs +4 -6
  85. package/esm2022/lib/part/view-context-menu/view-menu.directive.mjs +2 -2
  86. package/esm2022/lib/part/view-context-menu/view-menu.service.mjs +48 -49
  87. package/esm2022/lib/part/view-list/view-list.component.mjs +41 -48
  88. package/esm2022/lib/part/view-list-button/view-list-button.component.mjs +22 -26
  89. package/esm2022/lib/part/view-list-item/view-list-item.component.mjs +15 -17
  90. package/esm2022/lib/part/view-tab/view-tab.component.mjs +99 -110
  91. package/esm2022/lib/part/view-tab-content/view-tab-content.component.mjs +3 -4
  92. package/esm2022/lib/part/view-tab-drag-image/view-tab-drag-image.component.mjs +16 -17
  93. package/esm2022/lib/part/workbench-part-action.registry.mjs +18 -42
  94. package/esm2022/lib/part/workbench-part.model.mjs +10 -1
  95. package/esm2022/lib/part/workbench-part.registry.mjs +11 -45
  96. package/esm2022/lib/part//311/265workbench-part.model.mjs +71 -55
  97. package/esm2022/lib/perspective/workbench-grid-merger.service.mjs +3 -3
  98. package/esm2022/lib/perspective/workbench-perspective.model.mjs +1 -1
  99. package/esm2022/lib/perspective/workbench-perspective.registry.mjs +11 -43
  100. package/esm2022/lib/perspective/workbench-perspective.service.mjs +71 -62
  101. package/esm2022/lib/perspective/workench-perspective-serializer.service.mjs +2 -2
  102. package/esm2022/lib/perspective//311/265workbench-perspective.model.mjs +62 -47
  103. package/esm2022/lib/popup/popup.component.mjs +3 -3
  104. package/esm2022/lib/popup/popup.config.mjs +27 -25
  105. package/esm2022/lib/popup/popup.service.mjs +169 -174
  106. package/esm2022/lib/portal/wb-component-portal.mjs +18 -17
  107. package/esm2022/lib/public_api.mjs +1 -1
  108. package/esm2022/lib/registry/workbench-object-registry.mjs +38 -17
  109. package/esm2022/lib/routing/public_api.mjs +2 -2
  110. package/esm2022/lib/routing/routing.model.mjs +1 -1
  111. package/esm2022/lib/routing/routing.util.mjs +215 -0
  112. package/esm2022/lib/routing/workbench-auxiliary-route-installer.service.mjs +110 -0
  113. package/esm2022/lib/routing/workbench-dialog-differ.mjs +3 -3
  114. package/esm2022/lib/routing/workbench-layout-differ.mjs +3 -10
  115. package/esm2022/lib/routing/workbench-message-box-differ.mjs +3 -3
  116. package/esm2022/lib/routing/workbench-navigational-states.mjs +2 -2
  117. package/esm2022/lib/routing/workbench-popup-differ.mjs +3 -3
  118. package/esm2022/lib/routing/workbench-route-guards.mjs +57 -0
  119. package/esm2022/lib/routing/workbench-url-observer.service.mjs +140 -148
  120. package/esm2022/lib/routing/workbench-view-outlet-differ.mjs +58 -0
  121. package/esm2022/lib/routing//311/265workbench-router.service.mjs +119 -74
  122. package/esm2022/lib/startup/splash/splash.component.mjs +3 -3
  123. package/esm2022/lib/startup/workbench-launcher.service.mjs +22 -10
  124. package/esm2022/lib/testing/workbench.provider.mjs +2 -2
  125. package/esm2022/lib/theme/workbench-theme-switcher.service.mjs +15 -19
  126. package/esm2022/lib/view/public_api.mjs +1 -2
  127. package/esm2022/lib/view/view-move-handler.service.mjs +71 -56
  128. package/esm2022/lib/view/view-portal.pipe.mjs +7 -7
  129. package/esm2022/lib/view/view.component.mjs +54 -42
  130. package/esm2022/lib/view/workbench-view.model.mjs +1 -1
  131. package/esm2022/lib/view/workbench-view.registry.mjs +11 -45
  132. package/esm2022/lib/view//311/265workbench-view.model.mjs +183 -153
  133. package/esm2022/lib/view-dnd/grid-drop-targets.util.mjs +2 -2
  134. package/esm2022/lib/view-dnd/view-drag.service.mjs +87 -71
  135. package/esm2022/lib/view-dnd/view-drop-placeholder-renderer.service.mjs +6 -6
  136. package/esm2022/lib/view-dnd/view-drop-zone.directive.mjs +6 -6
  137. package/esm2022/lib/view-dnd/view-tab-drag-image-renderer.service.mjs +43 -56
  138. package/esm2022/lib/workbench-config.mjs +2 -2
  139. package/esm2022/lib/workbench-id.mjs +3 -3
  140. package/esm2022/lib/workbench.component.mjs +66 -54
  141. package/esm2022/lib/workbench.constants.mjs +1 -5
  142. package/esm2022/lib/workbench.model.mjs +1 -1
  143. package/esm2022/lib/workbench.provider.mjs +3 -9
  144. package/esm2022/lib/workbench.service.mjs +1 -1
  145. package/esm2022/lib//311/265workbench.service.mjs +38 -42
  146. package/fesm2022/scion-workbench.mjs +4054 -3276
  147. package/fesm2022/scion-workbench.mjs.map +1 -1
  148. package/lib/common/class-list.d.ts +35 -22
  149. package/lib/common/math.util.d.ts +7 -0
  150. package/lib/common/objects.util.d.ts +4 -0
  151. package/lib/common/operators.d.ts +1 -6
  152. package/lib/common/uid.util.d.ts +9 -0
  153. package/lib/content-projection/content-as-overlay.component.d.ts +39 -22
  154. package/lib/content-projection/workbench-element-references.d.ts +13 -0
  155. package/lib/dialog/workbench-dialog.component.d.ts +3 -2
  156. package/lib/dialog/workbench-dialog.d.ts +57 -13
  157. package/lib/dialog//311/265workbench-dialog.d.ts +38 -24
  158. package/lib/dialog//311/265workbench-dialog.service.d.ts +10 -11
  159. package/lib/executor/latest-task-executor.d.ts +26 -0
  160. package/lib/executor/single-task-executor.d.ts +5 -8
  161. package/lib/filter-field/filter-field.component.d.ts +1 -1
  162. package/lib/layout/grid-element/grid-element.component.d.ts +1 -8
  163. package/lib/layout/main-area-layout/main-area-layout.component.d.ts +0 -4
  164. package/lib/layout/migration/model/workbench-layout-migration-v5.model.d.ts +36 -0
  165. package/lib/layout/migration/model/workbench-layout-migration-v6.model.d.ts +35 -0
  166. package/lib/layout/migration/workbench-layout-migration-v5.service.d.ts +12 -0
  167. package/lib/layout/migration/workbench-layout-migration-v6.service.d.ts +12 -0
  168. package/lib/layout/stringifier.d.ts +26 -0
  169. package/lib/layout/workbench-layout.component.d.ts +4 -5
  170. package/lib/layout/workbench-layout.d.ts +9 -6
  171. package/lib/layout/workbench-layout.model.d.ts +4 -3
  172. package/lib/layout/workbench-layout.service.d.ts +14 -16
  173. package/lib/layout/workbench-layouts.util.d.ts +0 -6
  174. package/lib/layout/workench-layout-serializer.service.d.ts +13 -16
  175. package/lib/layout//311/265workbench-layout.d.ts +18 -19
  176. package/lib/layout//311/265workbench-layout.factory.d.ts +3 -2
  177. package/lib/logging//311/265logger.d.ts +2 -3
  178. package/lib/microfrontend-platform/common/microfrontend.util.d.ts +5 -1
  179. package/lib/microfrontend-platform/initialization/microfrontend-platform-initializer.service.d.ts +7 -3
  180. package/lib/microfrontend-platform/manifest-object-cache.service.d.ts +33 -0
  181. package/lib/microfrontend-platform/microfrontend-host-dialog/microfrontend-host-dialog.component.d.ts +3 -6
  182. package/lib/microfrontend-platform/microfrontend-host-message-box/microfrontend-host-message-box.component.d.ts +2 -1
  183. package/lib/microfrontend-platform/microfrontend-host-message-box/text-message/text-message.component.d.ts +1 -1
  184. package/lib/microfrontend-platform/microfrontend-host-popup/microfrontend-host-popup.component.d.ts +2 -1
  185. package/lib/microfrontend-platform/microfrontend-perspective/microfrontend-perspective-capability-validator.interceptor.d.ts +10 -0
  186. package/lib/microfrontend-platform/microfrontend-perspective/microfrontend-perspective-installer.service.d.ts +24 -0
  187. package/lib/microfrontend-platform/microfrontend-perspective/microfrontend-perspective-intent-handler.interceptor.d.ts +20 -0
  188. package/lib/microfrontend-platform/microfrontend-perspective/workbench-perspective-data.d.ts +9 -0
  189. package/lib/microfrontend-platform/microfrontend-popup/microfrontend-popup-intent-handler.interceptor.d.ts +4 -8
  190. package/lib/microfrontend-platform/microfrontend-popup/microfrontend-popup.component.d.ts +0 -4
  191. package/lib/microfrontend-platform/microfrontend-view/microfrontend-view-command-handler.service.d.ts +5 -12
  192. package/lib/microfrontend-platform/microfrontend-view/microfrontend-view.component.d.ts +23 -33
  193. package/lib/microfrontend-platform/public_api.d.ts +1 -0
  194. package/lib/microfrontend-platform/routing/microfrontend-view-capability-validator.interceptor.d.ts +1 -1
  195. package/lib/microfrontend-platform/routing/microfrontend-view-intent-handler.interceptor.d.ts +3 -7
  196. package/lib/microfrontend-platform/routing/microfrontend-view-routes.d.ts +9 -2
  197. package/lib/microfrontend-platform/stable-capability-id-assigner.interceptor.d.ts +11 -0
  198. package/lib/notification/notification-list.component.d.ts +0 -2
  199. package/lib/page-not-found/page-not-found.component.d.ts +1 -0
  200. package/lib/part/part-action-bar/part-action-bar.component.d.ts +3 -4
  201. package/lib/part/part-action-bar/part-action.directive.d.ts +2 -2
  202. package/lib/part/part-bar/part-bar.component.d.ts +73 -63
  203. package/lib/part/part-portal.pipe.d.ts +3 -5
  204. package/lib/part/part.component.d.ts +9 -12
  205. package/lib/part/view-context-menu/text.component.d.ts +3 -4
  206. package/lib/part/view-context-menu/view-menu.directive.d.ts +1 -1
  207. package/lib/part/view-context-menu/view-menu.service.d.ts +13 -17
  208. package/lib/part/view-list/view-list.component.d.ts +8 -21
  209. package/lib/part/view-list-button/view-list-button.component.d.ts +8 -11
  210. package/lib/part/view-list-item/view-list-item.component.d.ts +3 -7
  211. package/lib/part/view-tab/view-tab.component.d.ts +19 -29
  212. package/lib/part/view-tab-drag-image/view-tab-drag-image.component.d.ts +4 -4
  213. package/lib/part/workbench-part-action.registry.d.ts +3 -23
  214. package/lib/part/workbench-part.model.d.ts +8 -27
  215. package/lib/part/workbench-part.registry.d.ts +3 -26
  216. package/lib/part//311/265workbench-part.model.d.ts +23 -17
  217. package/lib/perspective/workbench-perspective.model.d.ts +18 -25
  218. package/lib/perspective/workbench-perspective.registry.d.ts +3 -26
  219. package/lib/perspective/workbench-perspective.service.d.ts +16 -14
  220. package/lib/perspective/workench-perspective-serializer.service.d.ts +1 -1
  221. package/lib/perspective//311/265workbench-perspective.model.d.ts +30 -21
  222. package/lib/popup/popup.config.d.ts +11 -10
  223. package/lib/popup/popup.service.d.ts +15 -28
  224. package/lib/portal/wb-component-portal.d.ts +21 -5
  225. package/lib/public_api.d.ts +1 -1
  226. package/lib/registry/workbench-object-registry.d.ts +10 -6
  227. package/lib/routing/public_api.d.ts +2 -2
  228. package/lib/routing/routing.model.d.ts +25 -13
  229. package/lib/routing/{router.util.d.ts → routing.util.d.ts} +28 -1
  230. package/lib/routing/{workbench-auxiliary-routes-registrator.service.d.ts → workbench-auxiliary-route-installer.service.d.ts} +10 -3
  231. package/lib/routing/workbench-layout-differ.d.ts +1 -2
  232. package/lib/routing/workbench-navigational-states.d.ts +8 -4
  233. package/lib/{view/workbench-view-route-guards.d.ts → routing/workbench-route-guards.d.ts} +8 -2
  234. package/lib/routing/workbench-url-observer.service.d.ts +31 -55
  235. package/lib/routing/workbench-view-outlet-differ.d.ts +32 -0
  236. package/lib/routing//311/265workbench-router.service.d.ts +22 -18
  237. package/lib/startup/workbench-launcher.service.d.ts +4 -5
  238. package/lib/testing/workbench.provider.d.ts +3 -1
  239. package/lib/theme/workbench-theme-switcher.service.d.ts +4 -6
  240. package/lib/view/public_api.d.ts +0 -1
  241. package/lib/view/view-move-handler.service.d.ts +16 -14
  242. package/lib/view/view-portal.pipe.d.ts +1 -3
  243. package/lib/view/view.component.d.ts +21 -12
  244. package/lib/view/workbench-view.model.d.ts +88 -36
  245. package/lib/view/workbench-view.registry.d.ts +3 -27
  246. package/lib/view//311/265workbench-view.model.d.ts +62 -71
  247. package/lib/view-dnd/view-drag.service.d.ts +79 -49
  248. package/lib/view-dnd/view-drop-placeholder-renderer.service.d.ts +1 -1
  249. package/lib/view-dnd/view-tab-drag-image-renderer.service.d.ts +12 -36
  250. package/lib/workbench-config.d.ts +19 -7
  251. package/lib/workbench.component.d.ts +16 -30
  252. package/lib/workbench.constants.d.ts +0 -5
  253. package/lib/workbench.model.d.ts +31 -3
  254. package/lib/workbench.service.d.ts +58 -56
  255. package/lib//311/265workbench.service.d.ts +18 -31
  256. package/package.json +5 -5
  257. package/esm2022/lib/common/filter-by-predicate.pipe.mjs +0 -27
  258. package/esm2022/lib/common/filter-by-text.pipe.mjs +0 -39
  259. package/esm2022/lib/common/uuid.util.mjs +0 -17
  260. package/esm2022/lib/content-projection/content-projection.directive.mjs +0 -101
  261. package/esm2022/lib/content-projection/view-container.reference.mjs +0 -68
  262. package/esm2022/lib/microfrontend-platform/routing/microfrontend-view-capability-id-assigner.interceptor.mjs +0 -41
  263. package/esm2022/lib/page-not-found/format-url.pipe.mjs +0 -26
  264. package/esm2022/lib/part/part-action-bar/part-action-filter.pipe.mjs +0 -26
  265. package/esm2022/lib/routing/router.util.mjs +0 -126
  266. package/esm2022/lib/routing/workbench-auxiliary-routes-registrator.service.mjs +0 -94
  267. package/esm2022/lib/view/workbench-view-route-guards.mjs +0 -47
  268. package/lib/common/filter-by-predicate.pipe.d.ts +0 -10
  269. package/lib/common/filter-by-text.pipe.d.ts +0 -12
  270. package/lib/common/uuid.util.d.ts +0 -8
  271. package/lib/content-projection/content-projection.directive.d.ts +0 -30
  272. package/lib/content-projection/view-container.reference.d.ts +0 -42
  273. package/lib/microfrontend-platform/routing/microfrontend-view-capability-id-assigner.interceptor.d.ts +0 -10
  274. package/lib/page-not-found/format-url.pipe.d.ts +0 -11
  275. package/lib/part/part-action-bar/part-action-filter.pipe.d.ts +0 -11
@@ -1,5 +1,5 @@
1
1
  /*
2
- * Copyright (c) 2018-2023 Swiss Federal Railways
2
+ * Copyright (c) 2018-2024 Swiss Federal Railways
3
3
  *
4
4
  * This program and the accompanying materials are made
5
5
  * available under the terms of the Eclipse Public License 2.0
@@ -7,43 +7,43 @@
7
7
  *
8
8
  * SPDX-License-Identifier: EPL-2.0
9
9
  */
10
- import { Component, ElementRef, HostListener, Inject, ViewChild, ViewChildren } from '@angular/core';
10
+ import { Component, computed, effect, ElementRef, HostListener, inject, NgZone, signal, untracked, viewChild, viewChildren } from '@angular/core';
11
11
  import { ViewTabComponent } from '../view-tab/view-tab.component';
12
- import { filter, map, mergeMap, startWith, switchMap, take, takeUntil } from 'rxjs/operators';
13
- import { animationFrameScheduler, BehaviorSubject, combineLatest, firstValueFrom, from, interval, Subject } from 'rxjs';
14
- import { ViewDragImageRect } from '../../view-dnd/view-tab-drag-image-renderer.service';
12
+ import { map, mergeMap, takeUntil } from 'rxjs/operators';
13
+ import { from, fromEvent, merge, Observable, Subject, timer } from 'rxjs';
14
+ import { ViewTabDragImageRenderer } from '../../view-dnd/view-tab-drag-image-renderer.service';
15
+ import { ViewDragService } from '../../view-dnd/view-drag.service';
15
16
  import { getCssTranslation, setCssClass, setCssVariable, unsetCssClass, unsetCssVariable } from '../../common/dom.util';
16
- import { filterArray, mapArray, observeInside, subscribeInside } from '@scion/toolkit/operators';
17
+ import { ɵWorkbenchPart } from '../ɵworkbench-part.model';
18
+ import { filterArray, subscribeIn } from '@scion/toolkit/operators';
17
19
  import { SciViewportComponent } from '@scion/components/viewport';
18
- import { SciDimensionModule } from '@scion/components/dimension';
19
- import { AsyncPipe, NgFor, NgIf } from '@angular/common';
20
+ import { ɵWorkbenchRouter } from '../../routing/ɵworkbench-router.service';
21
+ import { boundingClientRect, dimension } from '@scion/components/dimension';
20
22
  import { PartActionBarComponent } from '../part-action-bar/part-action-bar.component';
21
23
  import { ViewListButtonComponent } from '../view-list-button/view-list-button.component';
22
24
  import { takeUntilDestroyed } from '@angular/core/rxjs-interop';
23
- import { fromDimension$ } from '@scion/toolkit/observable';
24
25
  import { WORKBENCH_ID } from '../../workbench-id';
26
+ import { clamp } from '../../common/math.util';
25
27
  import * as i0 from "@angular/core";
26
- import * as i1 from "../../layout/workbench-layout.service";
27
- import * as i2 from "../../routing/\u0275workbench-router.service";
28
- import * as i3 from "../../view-dnd/view-tab-drag-image-renderer.service";
29
- import * as i4 from "../\u0275workbench-part.model";
30
- import * as i5 from "../../view-dnd/view-drag.service";
31
- import * as i6 from "@scion/components/dimension";
32
28
  /**
33
29
  * Renders view tabs and actions of a {@link WorkbenchPart}.
34
30
  *
35
31
  * Tabs are added to a viewport, which the user can scroll if not enough space. The viewport grows with its tabs,
36
32
  * allowing actions to be placed directly after the last tab or on the right side.
37
33
  *
38
- * ## Drag Events
34
+ * ## Drag and Drop
35
+ * This component subscribes to drag events to visualize tabs during a drag operation. The drag operation is initiated in {@link ViewTabComponent}.
36
+ *
39
37
  * We use native drag and drop to support dragging views to other windows.
40
38
  *
41
- * By listening to drag events, the tabbar visualizes tabs during a drag operation. The drag operation is initiated in {@link ViewTabComponent}.
42
- * - `dragstart` and `dragend` events are fired in the tabbar where the drag operation was initiated.
43
- * - `dragenter` event is fired when a tab enters the tabbar.
44
- * - `dragover` events are fired when dragging a tab over the tabbar.
45
- * - `dragleave` event is fired when a tab leaves the tabbar.
46
- * - `drop` event is fired when the user drops a tab in the tabbar.
39
+ * Following events are triggered:
40
+ * - dragstart: when start dragging a tab (only received in the tabbar where the drag operation has started)
41
+ * - dragend: when end dragging a tab, either via drop or cancel (only received in the tabbar where the drag operation has started)
42
+ * - dragenter: when a tab enters the tabbar
43
+ * - dragover: when dragging a tab over the tabbar, every few hundred milliseconds
44
+ * - dragleave: when a tab leaves the tabbar
45
+ * - drop: when the user drops a tab in the tabbar
46
+ *
47
47
  * - Note that `dragleave` event is not fired on drop action. Therefore, always handle both events, `dragleave` and `drop` events, respectively.
48
48
  *
49
49
  * ## Terminology
@@ -53,34 +53,34 @@ import * as i6 from "@scion/components/dimension";
53
53
  * e.g., to snap the drag image to the tabbar when dragging near it.
54
54
  */
55
55
  export class PartBarComponent {
56
- set injectViewTabs(queryList) {
57
- queryList.changes
58
- .pipe(startWith(queryList), takeUntilDestroyed(this._destroyRef))
59
- .subscribe(queryList => this._viewTabs$.next(queryList.toArray()));
60
- }
61
- constructor(host, _workbenchId, _workbenchLayoutService, _router, _viewTabDragImageRenderer, _part, _viewDragService, _destroyRef, _zone) {
62
- this._workbenchId = _workbenchId;
63
- this._workbenchLayoutService = _workbenchLayoutService;
64
- this._router = _router;
65
- this._viewTabDragImageRenderer = _viewTabDragImageRenderer;
66
- this._part = _part;
67
- this._viewDragService = _viewDragService;
68
- this._destroyRef = _destroyRef;
69
- this._zone = _zone;
56
+ constructor() {
57
+ this._host = inject((ElementRef)).nativeElement;
70
58
  this._viewportChange$ = new Subject();
71
- this._viewTabs$ = new BehaviorSubject([]);
72
- this._dragenter$ = new Subject();
73
- this._dragleave$ = new Subject();
74
- this._dragend$ = new Subject();
59
+ this._workbenchId = inject(WORKBENCH_ID);
60
+ this._router = inject(ɵWorkbenchRouter);
61
+ this._viewTabDragImageRenderer = inject(ViewTabDragImageRenderer);
62
+ this._viewDragService = inject(ViewDragService);
63
+ this._zone = inject(NgZone);
64
+ this._viewTabs = viewChildren(ViewTabComponent);
65
+ this._hostBoundingClientRect = boundingClientRect(inject(ElementRef));
66
+ this._viewportComponent = viewChild.required(SciViewportComponent);
67
+ this._viewportComponentElement = viewChild.required(SciViewportComponent, { read: (ElementRef) });
68
+ this._tabCornerRadiusElement = viewChild.required('tab_corner_radius', { read: (ElementRef) });
69
+ this._paddingInlineElement = viewChild.required('padding_inline', { read: (ElementRef) });
70
+ this._fillerElement = viewChild.required('filler');
71
+ this._viewportBoundingBox = boundingClientRect(this._viewportComponentElement);
72
+ this.part = inject(ɵWorkbenchPart);
73
+ this.startActions = computed(() => this.part.actions().filter(action => action.align !== 'end'));
74
+ this.endActions = computed(() => this.part.actions().filter(action => action.align === 'end'));
75
75
  /**
76
76
  * Reference to the tab before which to insert the drag source on drop, or `end` if dropping it after the last tab.
77
77
  */
78
- this.dropTargetViewTab = null;
78
+ this.dropTargetViewTab = signal(null);
79
79
  /**
80
80
  * Reference to the tab where the drag operation was started.
81
81
  * This reference is only set if the drag operation started on a tab of this tabbar.
82
82
  */
83
- this.dragSourceViewTab = null;
83
+ this.dragSourceViewTab = signal(null);
84
84
  /**
85
85
  * Transfer data of the tab being dragged over this tabbar.
86
86
  */
@@ -89,6 +89,10 @@ export class PartBarComponent {
89
89
  * Function for snapping the drag image to the tabbar when dragging near it.
90
90
  */
91
91
  this._constrainFn = null;
92
+ /**
93
+ * Signals when unsetting drag state.
94
+ */
95
+ this._onUnsetDragState = signal(undefined, { equal: () => false });
92
96
  /**
93
97
  * Tabbar indents where to display the rounded bottom corners of the first and last view tab.
94
98
  */
@@ -96,171 +100,186 @@ export class PartBarComponent {
96
100
  left: 0,
97
101
  right: 0,
98
102
  };
99
- /**
100
- * Notifies when the drag animation has finished, i.e., tabs have transitioned to their final position.
101
- */
102
- this._dragAnimationStable$ = interval(0, animationFrameScheduler)
103
- .pipe(filter(() => this.isDragAnimationStable()), subscribeInside(continueFn => this._zone.runOutsideAngular(continueFn)), observeInside(continueFn => this._zone.run(continueFn)), map(() => undefined));
104
- this._host = host.nativeElement;
105
- this.dragover$ = this._viewDragService.tabbarDragOver$.pipe(map(partId => partId === this._part.id));
106
- }
107
- ngOnInit() {
103
+ this._maxViewportWidth = this.calculateMaxViewportWidth();
108
104
  this.installActiveViewScroller();
109
105
  this.installScrolledIntoViewUpdater();
110
106
  this.installViewDragListener();
111
- this.installTabbarIndentSizeDetector();
112
- this.installViewportClientSizeDetector();
107
+ this.installTabbarIndentSizeTracker();
108
+ this.installViewportChangeTracker();
113
109
  }
114
110
  onDoubleClick(event) {
115
- if (this._part.isInMainArea) {
111
+ if (this.part.isInMainArea) {
116
112
  this._router.navigate(layout => layout.toggleMaximized()).then();
117
113
  }
118
114
  event.stopPropagation();
119
115
  }
120
- get viewIds$() {
121
- return this._part.viewIds$;
122
- }
123
- onTabbarViewportDimensionChange() {
124
- this._viewportChange$.next();
125
- }
126
- onScroll() {
127
- this._viewportChange$.next();
128
- }
129
116
  /**
130
- * Method invoked when the user starts dragging a tab of this tabbar.
117
+ * Method invoked when the user starts dragging a tab of this tabbar, only in the tabbar where the drag started.
131
118
  */
132
- onViewDragStart(event) {
133
- if (!this._viewDragService.isViewDragEvent(event)) {
134
- return;
135
- }
136
- const dragData = this._viewDragService.viewDragData;
137
- const dragSourceIndex = this._viewTabs.findIndex(viewTab => viewTab.viewId === dragData.viewId);
138
- const dragSourceViewTab = this._viewTabs[dragSourceIndex];
139
- const dropTargetViewTab = this._viewTabs[dragSourceIndex + 1] ?? 'end';
140
- // Constrain function for snapping the drag image to the tabbar when dragging near it.
119
+ onTabDragStart() {
120
+ // Memoize drag data.
121
+ this._dragData = this._viewDragService.viewDragData();
122
+ // Indicate dragging over this tabbar.
123
+ this._viewDragService.signalTabbarDragEnter(this.part.id);
124
+ // Snap drag image to tabbar when dragging near it.
141
125
  this._constrainFn = this.createDragImageConstrainFn();
142
126
  this._viewTabDragImageRenderer.setConstrainDragImageRectFn(this._constrainFn);
143
- this._viewDragService.setTabbarDragover(this._part.id);
144
- // When start dragging a view tab, we remove it from the tabbar by setting its `display` to `none` and render its drag image in `ViewTabDragImageRenderer` instead.
145
- // However, do not unset the `display` of the drag source during `dragstart`. Otherwise, the native drag operation would be corrupted in Chrome and Edge (but not in Firefox).
146
- animationFrameScheduler.schedule(() => {
147
- this.dragSourceViewTab = dragSourceViewTab;
148
- this.dropTargetViewTab = dropTargetViewTab; // Set drop target to avoid tab animation.
149
- setCssVariable(this._host, {
150
- '--ɵpart-bar-drag-source-width': `${dragData.viewTabWidth}px`,
151
- '--ɵpart-bar-drag-image-placeholder-width': `${dragData.viewTabWidth}px`,
152
- });
153
- });
154
- // When dragging a tab very quickly out of this tabbar, only the `dragstart` event gets fired, but not the `dragenter` event.
155
- // Therefore, we subscribe to global `dragenter` events and manually invoke `onTabbarDragLeave` to correctly display the tabs and the active view.
156
- this._viewDragService.viewDrag$(window, { eventType: ['dragenter'] })
157
- .pipe(take(1), takeUntil(this._dragend$), takeUntilDestroyed(this._destroyRef))
127
+ // Disable pointer events to not break the drag operation (in Firefox, but not Chrome and Edge).
128
+ requestAnimationFrame(() => setCssClass(this._host, 'pointer-events-disabled'));
129
+ // Set CSS class to not animate start dragging.
130
+ setCssClass(this._host, 'on-drag-start');
131
+ this.onDragAnimationStable(() => unsetCssClass(this._host, 'on-drag-start'));
132
+ // Check if the user continues dragging over this tabbar.
133
+ // If not, the user has quickly dragged the tab out of the tabbar, so manually call `onTabbarDragEnter` and `onTabbarDragLeave`.
134
+ fromEvent(window, 'dragenter', { once: true })
135
+ .pipe(takeUntil(merge(fromEvent(this._host, 'dragenter'), fromEvent(this._host, 'dragend'))))
158
136
  .subscribe(event => {
159
- // Check if the user continues dragging over this tabbar.
160
- // If not, the user has quickly dragged the tab out of the tabbar and we manually call `onTabbarDragLeave`.
161
- if ((this._host.compareDocumentPosition(event.target) & Node.DOCUMENT_POSITION_CONTAINED_BY) === 0) {
162
- this.onTabbarDragLeave();
163
- }
137
+ this.onTabbarDragEnter(event);
138
+ this.onTabbarDragLeave(event);
164
139
  });
165
140
  }
166
141
  /**
167
- * Method invoked when the user ends dragging a tab of this tabbar.
168
- *
169
- * Invoked only in the tabbar where the drag operation started, regardless of whether the drag operation was completed or canceled.
142
+ * Method invoked when the user ends dragging a tab of this tabbar, either by drop or cancel, only in the tabbar where the drag started.
170
143
  */
171
- onViewDragEnd() {
172
- this._dragend$.next();
173
- this.unsetDragState();
144
+ onTabDragEnd(event) {
145
+ // Unset drag state only on cancel, not on drop, to prevent tabs from temporarily reverting to their pre-drag state. Drag state is reset in `onTabMoved` after a drop.
146
+ if (event.dataTransfer.dropEffect === 'none') {
147
+ // Reactivate the drag source view on cancel.
148
+ this.dragSourceViewTab()?.view().activate({ skipLocationChange: true }).then();
149
+ // Unset drag state.
150
+ this.unsetDragState();
151
+ }
152
+ }
153
+ /**
154
+ * Method invoked when the layout has changed after a drop. The drop may not be related to a tab of this tabbar.
155
+ */
156
+ onTabMoved(event) {
157
+ // Unset drag state only if no new drag has started since the drop.
158
+ if (this._dragData?.uid === event.dragData?.uid) {
159
+ this.unsetDragState();
160
+ }
174
161
  }
175
162
  /**
176
163
  * Method invoked when the user drags a tab into this tabbar.
177
164
  */
178
165
  onTabbarDragEnter(event) {
179
- this._dragenter$.next();
180
- this._viewDragService.setTabbarDragover(this._part.id);
181
- this._dragData = this._viewDragService.viewDragData;
182
- // Constrain function for snapping the drag image to the tabbar when dragging near it.
183
- if (!this._constrainFn) {
184
- this._constrainFn = this.createDragImageConstrainFn();
185
- this._viewTabDragImageRenderer.setConstrainDragImageRectFn(this._constrainFn);
166
+ // Memoize drag data.
167
+ const dragData = this._dragData = this._viewDragService.viewDragData();
168
+ // Indicate dragging over this tabbar.
169
+ this._viewDragService.signalTabbarDragEnter(this.part.id);
170
+ // Snap drag image to tabbar when dragging near it.
171
+ this._constrainFn = this.createDragImageConstrainFn();
172
+ this._viewTabDragImageRenderer.setConstrainDragImageRectFn(this._constrainFn);
173
+ // Set drag source, but only if started the drag operation in this part.
174
+ // We do not set the drag source in `dragstart` to not break the drag operation (in Chrome and Edge, but not Firefox).
175
+ if (this._host.classList.contains('on-drag-start')) {
176
+ this.dragSourceViewTab.set(this._viewTabs().find(viewTab => viewTab.viewId === dragData.viewId) ?? null);
177
+ setCssVariable(this._host, { '--ɵpart-bar-drag-placeholder-width': `${dragData.viewTabWidth}px` });
186
178
  }
187
- // Locate drop target to have a nice animation for the drag source placeholder.
188
- this.dropTargetViewTab = this.computeDropTarget(event);
189
- // Set the CSS class 'drag-enter' to indicate entering the tabbar.
190
- setCssClass(this._host, 'drag-enter', 'drag-over');
191
- this._dragAnimationStable$
192
- .pipe(take(1), takeUntil(this._dragenter$), takeUntilDestroyed(this._destroyRef))
193
- .subscribe({ complete: () => unsetCssClass(this._host, 'drag-enter') });
194
- setCssVariable(this._host, {
195
- '--ɵpart-bar-drag-source-width': `${this._dragData.viewTabWidth}px`,
196
- '--ɵpart-bar-drag-image-placeholder-width': `${this._dragData.viewTabWidth}px`,
197
- });
179
+ // Locate the tab the user is dragging over.
180
+ this.dropTargetViewTab.set(this.computeDropTarget(event));
181
+ // Disable pointer events on the tabbar for a smoother drag and drop experience when quickly swapping tabs.
182
+ setCssClass(this._host, 'pointer-events-disabled');
183
+ // Set CSS class to animate entering the tabbar.
184
+ setCssClass(this._host, 'on-drag-enter');
185
+ this.onDragAnimationStable(() => unsetCssClass(this._host, 'on-drag-enter'));
186
+ // Inject drag source width into CSS.
187
+ setCssVariable(this._host, { '--ɵpart-bar-drag-source-width': `${dragData.viewTabWidth}px` });
198
188
  }
199
189
  /**
200
190
  * Method invoked when the user drags a tab out of this tabbar.
201
191
  */
202
- onTabbarDragLeave() {
203
- this._dragleave$.next();
204
- // Set the CSS class 'drag-leave' to indicate leaving the tabbar.
205
- setCssClass(this._host, 'drag-leave');
206
- this._dragAnimationStable$
207
- .pipe(take(1), takeUntil(this._dragleave$), takeUntilDestroyed(this._destroyRef))
208
- .subscribe({ complete: () => unsetCssClass(this._host, 'drag-leave') });
209
- this.unsetDragState({ unsetDragSource: false });
210
- // Activate the view next to the view being dragged out of this tabbar. But, do not push the navigation into browsing history stack.
211
- if (this.dragSourceViewTab && this.dragSourceViewTab.active) {
212
- this._router.navigate(layout => layout.activateAdjacentView(this.dragSourceViewTab.viewId), { skipLocationChange: true }).then();
192
+ onTabbarDragLeave(event) {
193
+ // Set CSS class to animate leaving the tabbar, but not when canceling the drag operation for instant reset.
194
+ // Pointer coordinates are not set when the drag operation is canceled or when dragging the tab out of the window.
195
+ if (event.screenX || event.screenY) {
196
+ setCssClass(this._host, 'on-drag-leave');
197
+ this.onDragAnimationStable(() => unsetCssClass(this._host, 'on-drag-leave'));
213
198
  }
199
+ // Activate the adjacent tab, only if the drag operation is not canceled.
200
+ // The drag event does not provide information about cancelation. Therefore, we wait for a macrotask, canceling it when receiving `dragend`, i.e., the drag operation has been canceled.
201
+ if (this.dragSourceViewTab()?.active) {
202
+ timer(0)
203
+ .pipe(takeUntil(fromEvent(window, 'dragend')))
204
+ .subscribe(() => this._router.navigate(layout => layout.activateAdjacentView(this.dragSourceViewTab().viewId), { skipLocationChange: true }));
205
+ }
206
+ // Clean up drag state.
207
+ this.unsetDragState({ unsetDragSource: false, unsetDragData: false });
214
208
  }
215
209
  /**
216
- * Method invoked while the user is dragging a tab over this tabbar.
210
+ * Method invoked when the user is dragging a tab over this tabbar.
217
211
  */
218
- onTabbarDragOver(event) {
212
+ onTabbarDragOver(event, dragDistance, scrollDistance) {
213
+ NgZone.assertNotInAngularZone();
219
214
  event.preventDefault(); // allow view drop
220
- // Locate the tab over which the user is dragging the tab, but only after pending transitions have ended to prevent tabs from sliding back and forth.
221
- if (this.isDragAnimationStable()) {
222
- this.dropTargetViewTab = this.computeDropTarget(event);
223
- // Synchronize the width of the drag source placeholder with the drag pointer position to move actions along with the pointer.
224
- setCssVariable(this._host, { '--ɵpart-bar-drag-image-placeholder-width': `${this.calculateDragImagePlaceholderWidth(event)}px` });
225
- }
215
+ // Locate the tab the user is dragging over.
216
+ // - Run in animation frame for better performance, most noticeable on lower CPU power.
217
+ // - Do not wait for the drag animation to complete for a smoother drag and drop experience when quickly moving the tab in the tabbar.
218
+ requestAnimationFrame(() => {
219
+ // Skip if the drag operation has ended.
220
+ if (this._viewDragService.isDragOverTabbar !== this.part.id) {
221
+ return;
222
+ }
223
+ // Ignore the drag distance if `drag-enter` animation is in progress to avoid incorrect drop target computation when dragging a tab from the left.
224
+ if (this._host.classList.contains('on-drag-enter')) {
225
+ this.dropTargetViewTab.set(this.computeDropTarget(event, 0));
226
+ }
227
+ // Compute drop target only when moving the drag pointer to prevent tabs from sliding back and forth (while animation is in progress)
228
+ else if (dragDistance) {
229
+ this.dropTargetViewTab.set(this.computeDropTarget(event, dragDistance));
230
+ }
231
+ // Compute drop target when scrolling the viewport, i.e., not moving the drag pointer but scrolling the viewport because placed the drag pointer at the viewport edges.
232
+ else if (scrollDistance) {
233
+ this.dropTargetViewTab.set(this.computeDropTarget(event, scrollDistance));
234
+ }
235
+ // Set CSS class to animate dragging over the tabbar.
236
+ setCssClass(this._host, 'drag-over');
237
+ // Calculate the new size of the drag source placeholder.
238
+ // The placeholder expands the viewport when dragging a tab to the right, moving part actions along with the dragover event.
239
+ setCssVariable(this._host, { '--ɵpart-bar-drag-placeholder-width': `${this.calculateDragPlaceholderWidth(event)}px` });
240
+ });
226
241
  }
227
242
  /**
228
243
  * Method invoked when the user drops a tab in this tabbar.
229
244
  */
230
- onTabbarDrop() {
245
+ async onTabbarDrop() {
246
+ const dragData = this._dragData;
247
+ const dropTargetViewTab = this.dropTargetViewTab();
248
+ const dropPosition = dropTargetViewTab === 'end' ? 'end' : this._viewTabs().indexOf(dropTargetViewTab);
231
249
  this._viewDragService.dispatchViewMoveEvent({
232
250
  source: {
233
- workbenchId: this._dragData.workbenchId,
234
- partId: this._dragData.partId,
235
- viewId: this._dragData.viewId,
236
- alternativeViewId: this._dragData.alternativeViewId,
237
- viewUrlSegments: this._dragData.viewUrlSegments,
238
- navigationHint: this._dragData.navigationHint,
239
- classList: this._dragData.classList,
251
+ workbenchId: dragData.workbenchId,
252
+ partId: dragData.partId,
253
+ viewId: dragData.viewId,
254
+ alternativeViewId: dragData.alternativeViewId,
255
+ viewUrlSegments: dragData.viewUrlSegments,
256
+ navigationHint: dragData.navigationHint,
257
+ navigationData: dragData.navigationData,
258
+ classList: dragData.classList,
240
259
  },
241
260
  target: {
242
261
  workbenchId: this._workbenchId,
243
- position: this.dropTargetViewTab === 'end' ? 'end' : this._viewTabs.indexOf(this.dropTargetViewTab),
244
- elementId: this._part.id,
262
+ position: dropPosition,
263
+ elementId: this.part.id,
245
264
  },
246
- });
247
- // Wait undoing the drag state until flushed tab changes to the DOM, i.e., after the layout routing cycle completes.
248
- // If we were to undo the drag state immediately during the course of the drop event, the tab layout would temporarily
249
- // revert to the state before the drag operation, resulting in an ugly flicker.
250
- firstValueFrom(this._workbenchLayoutService.onLayoutChange$).then(() => {
251
- this.unsetDragState();
265
+ dragData: dragData,
252
266
  });
253
267
  }
254
268
  /**
255
269
  * Locates the tab before which the dragged tab is to be inserted when it is dropped. Dragging beyond the last tab returns `end`.
256
270
  */
257
- computeDropTarget(event) {
258
- const viewDragImageRect = this._viewTabDragImageRenderer.calculateDragImageRect(this._dragData, event);
259
- const viewTabs = this._viewTabs.filter(viewTab => viewTab !== this.dragSourceViewTab);
271
+ computeDropTarget(event, dragDistanceX = 0) {
272
+ const dragImage = this._viewTabDragImageRenderer.calculateDragImageRect(this._dragData, event);
273
+ const viewTabs = this._viewTabs().filter(viewTab => viewTab !== this.dragSourceViewTab());
260
274
  for (const viewTab of viewTabs) {
261
- const viewTabRect = viewTab.host.getBoundingClientRect();
262
- const viewTabMiddle = viewTabRect.left + (viewTabRect.width / 2);
263
- if (viewDragImageRect.left < viewTabMiddle && (viewTab !== this.dropTargetViewTab || viewDragImageRect.right < viewTabMiddle)) {
275
+ const { left, width } = viewTab.boundingClientRect();
276
+ const viewTabHCenter = left + (width / 2);
277
+ // Moving the pointer to the left.
278
+ if (dragDistanceX <= 0 && dragImage.left < viewTabHCenter) {
279
+ return viewTab;
280
+ }
281
+ // Moving the pinter to the right.
282
+ if (dragDistanceX > 0 && dragImage.right < viewTabHCenter) {
264
283
  return viewTab;
265
284
  }
266
285
  }
@@ -270,49 +289,32 @@ export class PartBarComponent {
270
289
  * Creates the function for snapping the drag image to the tabbar when dragging near it.
271
290
  */
272
291
  createDragImageConstrainFn() {
273
- const hostLeft = this._host.getBoundingClientRect().left;
274
- const maxViewportWidth = this.calculateMaxViewportWidth();
275
- return (rect) => {
276
- const viewportBoundingBox = this._viewportElement.nativeElement.getBoundingClientRect();
277
- return new ViewDragImageRect({
278
- x: Math.min(Math.max(hostLeft + this._tabbarIndent.left, rect.x), hostLeft + maxViewportWidth - rect.width - this._tabbarIndent.right),
279
- y: viewportBoundingBox.top,
280
- width: rect.width,
281
- height: viewportBoundingBox.height, // fit into tabbar, e.g., when dragging a tab into a tabbar of a different height
282
- });
283
- };
292
+ return (dragImage) => new DOMRect(clamp(dragImage.x, {
293
+ min: this._hostBoundingClientRect().left + this._tabbarIndent.left,
294
+ max: this._hostBoundingClientRect().left + this._maxViewportWidth() - dragImage.width - this._tabbarIndent.right,
295
+ }), this._viewportBoundingBox().top, dragImage.width, this._viewportBoundingBox().height);
284
296
  }
285
297
  /**
286
- * Calculates the maximum width of the tabbar viewport before an overflow would occur, which can then be used to constrain the drag image.
287
- *
288
- * To calculate the effective width, we need to simulate an overflow in the DOM. Therefore, call this method only from `dragstart` and not
289
- * from `dragover` and disable animations.
298
+ * Calculates the maximum width of the tabbar viewport before an overflow would occur.
299
+ * Use to constrain the drag image to the tabbar bounds.
290
300
  */
291
301
  calculateMaxViewportWidth() {
292
- const currentWidth = this._host.style.getPropertyValue('--ɵpart-bar-drag-image-placeholder-width');
293
- // Disable animations during calculation and force the viewport to overflow.
294
- setCssClass(this._host, 'calculating-max-viewport-width');
295
- setCssVariable(this._host, { '--ɵpart-bar-drag-image-placeholder-width': `${this._host.clientWidth}px` });
296
- try {
297
- return this._viewportElement.nativeElement.getBoundingClientRect().width;
298
- }
299
- finally {
300
- setCssVariable(this._host, { '--ɵpart-bar-drag-image-placeholder-width': currentWidth || null });
301
- unsetCssClass(this._host, 'calculating-max-viewport-width');
302
- }
302
+ const fillerDimension = dimension(this._fillerElement);
303
+ return computed(() => this._viewportBoundingBox().width + fillerDimension().offsetWidth);
303
304
  }
304
305
  /**
305
- * Calculates the width for the drag image placeholder.
306
+ * Calculates the width for the drag placeholder.
306
307
  *
308
+ * The placeholder expands the viewport when dragging a tab to the right, moving part actions along with the dragover event.
309
+ *
310
+ * Calculation:
307
311
  * - When dragging over tabs, the width is equal to the width of the drag source.
308
- * - When dragging to the right of the last tab, the width of the placeholder is calculated as the distance between the
309
- * last tab and the position of the dragover event. Applying this width will resize the viewport, moving part actions along
310
- * with the dragover event.
312
+ * - When dragging to the right of the last tab, the width of the placeholder is the distance between the last tab and the position of the drag pointer.
311
313
  */
312
- calculateDragImagePlaceholderWidth(event) {
314
+ calculateDragPlaceholderWidth(event) {
313
315
  const viewDragImageRect = this._viewTabDragImageRenderer.calculateDragImageRect(this._dragData, event);
314
- const lastViewTab = this._viewTabs.filter(viewTab => viewTab !== this.dragSourceViewTab).at(-1);
315
- const lastViewTabRight = lastViewTab?.host.getBoundingClientRect().right ?? this._host.getBoundingClientRect().left + this._tabbarIndent.left;
316
+ const lastViewTab = this._viewTabs().filter(viewTab => viewTab !== this.dragSourceViewTab()).at(-1);
317
+ const lastViewTabRight = lastViewTab?.boundingClientRect().right ?? this._hostBoundingClientRect().left + this._tabbarIndent.left;
316
318
  return Math.max(lastViewTabRight + viewDragImageRect.width, viewDragImageRect.right) - lastViewTabRight;
317
319
  }
318
320
  /**
@@ -320,11 +322,12 @@ export class PartBarComponent {
320
322
  * The animation is considered stable when all tabs have moved to their final position.
321
323
  */
322
324
  isDragAnimationStable() {
323
- if (!this.dropTargetViewTab) {
324
- return this._viewTabs.every(viewTab => getCssTranslation(viewTab.host).translateX === 'none');
325
+ const dropTargetViewTab = this.dropTargetViewTab();
326
+ if (this._viewDragService.isDragOverTabbar !== this.part.id) {
327
+ return this._viewTabs().every(viewTab => getCssTranslation(viewTab.host).translateX === 'none');
325
328
  }
326
- const viewTabs = this._viewTabs.filter(viewTab => viewTab !== this.dragSourceViewTab);
327
- const dropTargetIndex = this.dropTargetViewTab === 'end' ? viewTabs.length : viewTabs.indexOf(this.dropTargetViewTab);
329
+ const viewTabs = this._viewTabs().filter(viewTab => viewTab !== this.dragSourceViewTab());
330
+ const dropTargetIndex = dropTargetViewTab === 'end' ? viewTabs.length : viewTabs.indexOf(dropTargetViewTab);
328
331
  const dragSourceWidth = this._dragData.viewTabWidth;
329
332
  return viewTabs.every((viewTab, i) => {
330
333
  const viewTabTranslateX = getCssTranslation(viewTab.host).translateX;
@@ -339,33 +342,63 @@ export class PartBarComponent {
339
342
  return true;
340
343
  });
341
344
  }
345
+ /**
346
+ * Cleans up the drag state, unsetting drag data and drag source based on provided options.
347
+ */
342
348
  unsetDragState(options) {
343
- if (options?.unsetDragSource ?? true) {
344
- this.dragSourceViewTab = null;
345
- }
346
- this.dropTargetViewTab = null;
347
- this._dragData = null;
349
+ this.dropTargetViewTab.set(null);
350
+ this._onUnsetDragState.set();
348
351
  this._viewTabDragImageRenderer.unsetConstrainDragImageRectFn(this._constrainFn);
352
+ this._viewDragService.signalTabbarDragLeave(this.part.id);
349
353
  this._constrainFn = null;
350
- unsetCssClass(this._host, 'drag-over');
351
- unsetCssVariable(this._host, '--ɵpart-bar-drag-source-width', '--ɵpart-bar-drag-image-placeholder-width');
352
- this._viewDragService.unsetTabbarDragover(this._part.id);
354
+ unsetCssClass(this._host, 'drag-over', 'pointer-events-disabled');
355
+ unsetCssVariable(this._host, '--ɵpart-bar-drag-source-width', '--ɵpart-bar-drag-placeholder-width');
356
+ if (options?.unsetDragSource ?? true) {
357
+ this.dragSourceViewTab.set(null);
358
+ }
359
+ if (options?.unsetDragData ?? true) {
360
+ this._dragData = null;
361
+ }
353
362
  }
354
- get _viewTabs() {
355
- return this._viewTabs$.value;
363
+ /**
364
+ * Executes given function when the drag animation has finished, i.e., tabs have transitioned to their final position.
365
+ */
366
+ onDragAnimationStable(callback) {
367
+ if (NgZone.isInAngularZone()) {
368
+ this._zone.runOutsideAngular(() => this.onDragAnimationStable(callback));
369
+ return;
370
+ }
371
+ requestAnimationFrame(() => this.isDragAnimationStable() ? callback() : this.onDragAnimationStable(callback));
356
372
  }
357
373
  /**
358
374
  * Scrolls the tab of the active view into view.
359
375
  */
360
376
  installActiveViewScroller() {
361
- this._viewTabs$
362
- .pipe(switchMap(viewTabs => combineLatest(viewTabs.map(viewTab => viewTab.view.active$))), takeUntilDestroyed(this._destroyRef))
363
- .subscribe(() => {
364
- // There may be no active view in the tabbar, e.g., when dragging the last view out of the tabbar.
365
- const activeViewTab = this._viewTabs.find(viewTab => viewTab.active);
366
- if (activeViewTab && !this._viewportComponent.isElementInView(activeViewTab.host, 'full')) {
367
- this._viewportComponent.scrollIntoView(activeViewTab.host);
377
+ effect(() => {
378
+ // Track the active view.
379
+ const activeViewId = this.part.activeViewId();
380
+ // There may be no active view, e.g., if no view has been activated, or when dragging the last view out of the tabbar.
381
+ if (!activeViewId) {
382
+ return;
368
383
  }
384
+ // Do not track rendered tabs in general to prevent unwanted scrolling when opening or closing inactive tabs.
385
+ const viewTabs = untracked(() => this._viewTabs());
386
+ // Get a reference to the currently rendered active tab, waiting if necessary by tracking the rendered tabs.
387
+ const activeViewTab = viewTabs.find(viewTab => viewTab.viewId === activeViewId);
388
+ if (!activeViewTab) {
389
+ this._viewTabs(); // Track rendered tabs to re-execute once rendered.
390
+ return;
391
+ }
392
+ // Track navigation of the active view, scrolling its tab into view if necessary.
393
+ activeViewTab.view().navigationId();
394
+ // Track unsetting drag state to ensure the active view is scrolled into view after drop or cancel.
395
+ this._onUnsetDragState();
396
+ // Scroll the tab into view if scrolled out of view.
397
+ untracked(() => requestAnimationFrame(() => {
398
+ if (!this._viewportComponent().isElementInView(activeViewTab.host, 'full')) {
399
+ this._viewportComponent().scrollIntoView(activeViewTab.host);
400
+ }
401
+ }));
369
402
  });
370
403
  }
371
404
  /**
@@ -373,87 +406,123 @@ export class PartBarComponent {
373
406
  */
374
407
  installScrolledIntoViewUpdater() {
375
408
  this._viewportChange$
376
- .pipe(map(() => this._viewTabs), filterArray(viewTab => viewTab !== this.dragSourceViewTab), // skip drag source as always scrolled out of view
377
- mergeMap(viewTabs => from(viewTabs)), takeUntilDestroyed(this._destroyRef))
409
+ .pipe(map(() => this._viewTabs()), filterArray(viewTab => viewTab !== this.dragSourceViewTab()), // skip drag source as always scrolled out of view
410
+ mergeMap(viewTabs => from(viewTabs)), takeUntilDestroyed())
378
411
  .subscribe(viewTab => {
379
- viewTab.view.scrolledIntoView = this._viewportComponent.isElementInView(viewTab.host, 'full');
412
+ viewTab.view().scrolledIntoView = this._viewportComponent().isElementInView(viewTab.host, 'full');
380
413
  });
381
414
  }
415
+ /**
416
+ * Subscribes to drag events.
417
+ */
382
418
  installViewDragListener() {
419
+ const zone = inject(NgZone);
420
+ // Subscribe to drag events relevant for this tabbar.
383
421
  this._viewDragService.viewDrag$(this._host)
384
- .pipe(takeUntilDestroyed(this._destroyRef))
385
- .subscribe((event) => {
422
+ .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)), calculateDistance(() => this._viewportComponent()), // provide viewport lazily because not injected yet
423
+ takeUntilDestroyed())
424
+ .subscribe(({ event, dragDistance, scrollDistance }) => {
386
425
  switch (event.type) {
426
+ case 'dragstart':
427
+ this.onTabDragStart();
428
+ break;
429
+ case 'dragend':
430
+ this.onTabDragEnd(event);
431
+ break;
387
432
  case 'dragenter':
388
433
  this.onTabbarDragEnter(event);
389
434
  break;
390
435
  case 'dragover':
391
- this.onTabbarDragOver(event);
436
+ this.onTabbarDragOver(event, dragDistance, scrollDistance);
392
437
  break;
393
438
  case 'dragleave':
394
- this.onTabbarDragLeave();
439
+ this.onTabbarDragLeave(event);
395
440
  break;
396
441
  case 'drop':
397
- this.onTabbarDrop();
442
+ this.onTabbarDrop().then();
398
443
  break;
399
444
  }
400
445
  });
446
+ // Get notified when a view has moved in the layout.
447
+ this._viewDragService.viewMoved$
448
+ .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)), takeUntilDestroyed())
449
+ .subscribe(event => this.onTabMoved(event));
450
+ /**
451
+ * Calculates the distance the drag pointer and viewport have moved since the last drag event.
452
+ */
453
+ function calculateDistance(viewport) {
454
+ return source$ => new Observable(observer => {
455
+ let lastScreenX;
456
+ let lastScrollLeft;
457
+ const subscription = source$.subscribe(event => {
458
+ observer.next({
459
+ event,
460
+ dragDistance: event.screenX - (lastScreenX ?? event.screenX),
461
+ scrollDistance: viewport().scrollLeft - (lastScrollLeft ?? viewport().scrollLeft),
462
+ });
463
+ lastScreenX = event.screenX;
464
+ lastScrollLeft = viewport().scrollLeft;
465
+ });
466
+ return () => subscription.unsubscribe();
467
+ });
468
+ }
401
469
  }
402
- installViewportClientSizeDetector() {
403
- fromDimension$(this._viewportComponent.viewportClientElement)
404
- .pipe(subscribeInside(fn => this._zone.run(fn)), takeUntilDestroyed(this._destroyRef))
405
- .subscribe(() => this._viewportChange$.next());
470
+ /**
471
+ * Emits on {@link _viewportChange$} when the viewport size or scroll position changes.
472
+ */
473
+ installViewportChangeTracker() {
474
+ const viewportSize = dimension(computed(() => this._viewportComponentElement().nativeElement));
475
+ const viewportClientSize = dimension(computed(() => this._viewportComponent().viewportClientElement));
476
+ const zone = inject(NgZone);
477
+ // Detect resizing.
478
+ effect(() => {
479
+ // Track viewport and viewport client sizes.
480
+ viewportSize();
481
+ viewportClientSize();
482
+ untracked(() => this._viewportChange$.next());
483
+ });
484
+ // Detect scrolling.
485
+ effect(onCleanup => {
486
+ const viewport = this._viewportComponent().viewportElement;
487
+ untracked(() => {
488
+ const subscription = fromEvent(viewport, 'scroll')
489
+ .pipe(subscribeIn(fn => zone.runOutsideAngular(fn)))
490
+ .subscribe(() => this._viewportChange$.next());
491
+ onCleanup(() => subscription.unsubscribe());
492
+ });
493
+ });
406
494
  }
407
- installTabbarIndentSizeDetector() {
408
- combineLatest([fromDimension$(this._tabCornerRadiusElement.nativeElement), fromDimension$(this._paddingInlineElement.nativeElement)])
409
- .pipe(subscribeInside(fn => this._zone.runOutsideAngular(fn)), mapArray(dimension => dimension.clientWidth), takeUntilDestroyed(this._destroyRef))
410
- .subscribe(([tabCornerRadius, paddingInline]) => {
411
- this._tabbarIndent = { left: tabCornerRadius + paddingInline, right: tabCornerRadius + paddingInline };
412
- setCssVariable(this._host, { '--ɵpart-bar-indent-left': `${this._tabbarIndent.left}px` });
413
- setCssVariable(this._host, { '--ɵpart-bar-indent-right': `${this._tabbarIndent.right}px` });
495
+ /**
496
+ * Tracks the tabbar indents.
497
+ */
498
+ installTabbarIndentSizeTracker() {
499
+ const tabCornerRadiusDimension = dimension(this._tabCornerRadiusElement);
500
+ const paddingInlineDimension = dimension(this._paddingInlineElement);
501
+ effect(() => {
502
+ const indent = tabCornerRadiusDimension().clientWidth + paddingInlineDimension().clientWidth;
503
+ this._tabbarIndent = { left: indent, right: indent };
504
+ setCssVariable(this._host, {
505
+ '--ɵpart-bar-indent-left': `${this._tabbarIndent.left}px`,
506
+ '--ɵpart-bar-indent-right': `${this._tabbarIndent.right}px`,
507
+ });
414
508
  });
415
509
  }
416
- static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: PartBarComponent, deps: [{ token: i0.ElementRef }, { token: WORKBENCH_ID }, { token: i1.WorkbenchLayoutService }, { token: i2.ɵWorkbenchRouter }, { token: i3.ViewTabDragImageRenderer }, { token: i4.ɵWorkbenchPart }, { token: i5.ViewDragService }, { token: i0.DestroyRef }, { token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Component }); }
417
- static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "18.0.2", type: PartBarComponent, isStandalone: true, selector: "wb-part-bar", host: { listeners: { "dblclick": "onDoubleClick($event)", "dragstart": "onViewDragStart($event)", "dragend": "onViewDragEnd()" } }, viewQueries: [{ propertyName: "_viewportElement", first: true, predicate: SciViewportComponent, descendants: true, read: ElementRef, static: true }, { propertyName: "_viewportComponent", first: true, predicate: SciViewportComponent, descendants: true, static: true }, { propertyName: "_tabCornerRadiusElement", first: true, predicate: ["tab_corner_radius"], descendants: true, static: true }, { propertyName: "_paddingInlineElement", first: true, predicate: ["padding_inline"], descendants: true, static: true }, { propertyName: "injectViewTabs", predicate: ViewTabComponent, descendants: true }], ngImport: i0, template: "<sci-viewport class=\"tabbar\" scrollbarStyle=\"hidden\"\n [class.dragover]=\"dragover$ | async\"\n sciDimension (sciDimensionChange)=\"onTabbarViewportDimensionChange()\"\n (scroll)=\"onScroll()\">\n <ng-container *ngFor=\"let viewId of viewIds$ | async;\">\n <div class=\"divider\" *ngIf=\"viewtab === dropTargetViewTab\"></div>\n <wb-view-tab #viewtab\n [viewId]=\"viewId\"\n [class.drag-source]=\"viewtab === dragSourceViewTab\"\n [class.drop-target]=\"viewtab === dropTargetViewTab\">\n </wb-view-tab>\n <div class=\"divider\"></div>\n </ng-container>\n\n <!-- Placeholder element to grow the viewport to fit the drag image. -->\n <div class=\"drag-image-placeholder\"></div>\n</sci-viewport>\n<wb-part-action-bar/>\n<wb-view-list-button/>\n\n<!-- Element for injecting the corner radius into the component. -->\n<div class=\"tab-corner-radius\" #tab_corner_radius></div>\n<!-- Element for injecting the tabbar padding into the component. -->\n<div class=\"padding-inline\" #padding_inline></div>\n", styles: ["@charset \"UTF-8\";:host{--\\275part-bar-indent-left: 0;--\\275part-bar-indent-right: 0;--\\275part-bar-drag-source-width: 0;--\\275part-bar-drag-image-placeholder-width: 0;display:flex;color:var(--sci-workbench-tab-text-color);background-color:var(--sci-workbench-part-bar-background-color);border-top:var(--sci-workbench-part-bar-padding-top) solid transparent;background-clip:border-box;height:var(--sci-workbench-tab-height);box-sizing:content-box;position:relative;container-name:viewtab;container-type:size}wb-workbench:has(wb-main-area-layout) wb-part:not(.main-area) :host{background-color:var(--sci-workbench-part-peripheral-bar-background-color)}:host>sci-viewport.tabbar{flex:initial}:host>sci-viewport.tabbar::part(content){display:flex;padding-left:var(--\\275part-bar-indent-left);padding-right:var(--\\275part-bar-indent-right)}:host>sci-viewport.tabbar:not(.dragover):not(:has(wb-view-tab:not(.drag-source)))::part(content){padding-right:0}:host>sci-viewport.tabbar>wb-view-tab{flex:none}:host>sci-viewport.tabbar>wb-view-tab.drag-source{display:none}:host>sci-viewport.tabbar>div.divider{flex:none;display:flex;position:relative;width:0}:host>sci-viewport.tabbar>div.divider:after{flex:none;align-self:center;content:\"\";position:absolute;width:1px;left:-1px;height:65%;background-color:var(--sci-workbench-part-bar-divider-color)}:host>sci-viewport.tabbar>div.drag-image-placeholder{flex:none;width:var(--\\275part-bar-drag-image-placeholder-width)}:host>sci-viewport.tabbar>wb-view-tab.drop-target,:host>sci-viewport.tabbar wb-view-tab.drop-target~:is(wb-view-tab,div.divider),:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drop-target){transform:translate(var(--\\275part-bar-drag-source-width))}:host>sci-viewport.tabbar>wb-view-tab:is(.active,.drag-source)+div.divider{display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.active:not(.drag-source)){display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drag-source:not(.active)){display:none}:host>wb-part-action-bar{flex:auto}:host>wb-view-list-button{flex:none}:host:before{content:\"\";position:absolute;bottom:0;left:0;right:0;height:1px;background-color:var(--sci-workbench-tab-border-color)}:host>div.tab-corner-radius{position:absolute;visibility:hidden;width:var(--sci-workbench-tab-border-radius)}:host>div.padding-inline{position:absolute;visibility:hidden;width:var(--sci-workbench-part-bar-padding-inline)}:host:not(.calculating-max-viewport-width).drag-enter wb-view-tab,:host:not(.calculating-max-viewport-width).drag-enter div.divider,:host:not(.calculating-max-viewport-width).drag-over wb-view-tab,:host:not(.calculating-max-viewport-width).drag-over div.divider,:host:not(.calculating-max-viewport-width).drag-leave wb-view-tab,:host:not(.calculating-max-viewport-width).drag-leave div.divider{transition:transform 175ms cubic-bezier(0,0,.2,1)}:host:not(.calculating-max-viewport-width).drag-enter div.drag-image-placeholder,:host:not(.calculating-max-viewport-width).drag-leave div.drag-image-placeholder{transition:width 175ms cubic-bezier(0,0,.2,1)}\n"], dependencies: [{ kind: "directive", type: NgFor, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "component", type: SciViewportComponent, selector: "sci-viewport", inputs: ["scrollbarStyle"], outputs: ["scroll"] }, { kind: "ngmodule", type: SciDimensionModule }, { kind: "directive", type: i6.SciDimensionDirective, selector: "[sciDimension]", inputs: ["emitOutsideAngular"], outputs: ["sciDimensionChange"], exportAs: ["sciDimension"] }, { kind: "component", type: ViewTabComponent, selector: "wb-view-tab", inputs: ["viewId"] }, { kind: "component", type: PartActionBarComponent, selector: "wb-part-action-bar" }, { kind: "component", type: ViewListButtonComponent, selector: "wb-view-list-button" }, { kind: "directive", type: NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }] }); }
510
+ ngOnDestroy() {
511
+ this.unsetDragState();
512
+ }
513
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: PartBarComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
514
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.0.2", type: PartBarComponent, isStandalone: true, selector: "wb-part-bar", host: { listeners: { "dblclick": "onDoubleClick($event)" } }, viewQueries: [{ propertyName: "_viewTabs", predicate: ViewTabComponent, descendants: true, isSignal: true }, { propertyName: "_viewportComponent", first: true, predicate: SciViewportComponent, descendants: true, isSignal: true }, { propertyName: "_viewportComponentElement", first: true, predicate: SciViewportComponent, descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_tabCornerRadiusElement", first: true, predicate: ["tab_corner_radius"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_paddingInlineElement", first: true, predicate: ["padding_inline"], descendants: true, read: ElementRef, isSignal: true }, { propertyName: "_fillerElement", first: true, predicate: ["filler"], descendants: true, isSignal: true }], ngImport: i0, template: "<sci-viewport class=\"tabbar e2e-tabbar\" scrollbarStyle=\"hidden\">\n @for (viewId of part.viewIds(); track viewId) {\n @if (viewtab === dropTargetViewTab()) {\n <div class=\"divider\"></div>\n }\n <wb-view-tab #viewtab\n [viewId]=\"viewId\"\n [class.drag-source]=\"viewtab === dragSourceViewTab()\"\n [class.drop-target]=\"viewtab === dropTargetViewTab()\"/>\n <div class=\"divider\"></div>\n }\n\n <!-- Placeholder for expanding the viewport when dragging a tab to the right, moving part actions along with the dragover event. -->\n <div class=\"drag-placeholder\"></div>\n</sci-viewport>\n\n<!-- Actions -->\n@if (startActions().length) {\n <wb-part-action-bar [actions]=\"startActions()\" class=\"start\"/>\n}\n<div class=\"filler\" #filler></div>\n@if (endActions().length) {\n <wb-part-action-bar [actions]=\"endActions()\" class=\"end\"/>\n}\n\n<!-- View List Dropdown -->\n<wb-view-list-button/>\n\n<!-- Element for injecting the corner radius into the component. -->\n<div class=\"tab-corner-radius\" #tab_corner_radius></div>\n<!-- Element for injecting the tabbar padding into the component. -->\n<div class=\"padding-inline\" #padding_inline></div>\n", styles: ["@charset \"UTF-8\";:host{--\\275part-bar-indent-left: 0;--\\275part-bar-indent-right: 0;--\\275part-bar-drag-source-width: 0;--\\275part-bar-drag-placeholder-width: 0;display:flex;color:var(--sci-workbench-tab-text-color);background-color:var(--sci-workbench-part-bar-background-color);border-top:var(--sci-workbench-part-bar-padding-top) solid transparent;background-clip:border-box;height:var(--sci-workbench-tab-height);box-sizing:content-box;position:relative;container-name:viewtab;container-type:size}wb-workbench:has(wb-main-area-layout) wb-part:not(.main-area) :host{background-color:var(--sci-workbench-part-peripheral-bar-background-color)}:host>sci-viewport.tabbar{flex:initial}:host>sci-viewport.tabbar::part(content){display:flex;padding-left:var(--\\275part-bar-indent-left);padding-right:var(--\\275part-bar-indent-right)}:host>sci-viewport.tabbar>wb-view-tab{flex:none}:host>sci-viewport.tabbar>wb-view-tab.drag-source{display:none}:host>sci-viewport.tabbar>div.divider{flex:none;display:flex;position:relative;width:0}:host>sci-viewport.tabbar>div.divider:after{flex:none;align-self:center;content:\"\";position:absolute;width:1px;left:-1px;height:65%;background-color:var(--sci-workbench-part-bar-divider-color)}:host>sci-viewport.tabbar>div.drag-placeholder{flex:none;width:var(--\\275part-bar-drag-placeholder-width)}:host>sci-viewport.tabbar>wb-view-tab.drop-target,:host>sci-viewport.tabbar wb-view-tab.drop-target~:is(wb-view-tab,div.divider),:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drop-target){transform:translate(var(--\\275part-bar-drag-source-width))}:host>sci-viewport.tabbar>wb-view-tab:is(.active,.drag-source)+div.divider{display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.active:not(.drag-source)){display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drag-source:not(.active)){display:none}:host:not(.drag-over)>sci-viewport.tabbar:not(:has(wb-view-tab:not(.drag-source)))::part(content){padding-right:0}:host>wb-part-action-bar.start{flex:none;padding-left:var(--sci-workbench-part-bar-actions-padding-inline)}:host>div.filler{flex:auto}:host>wb-part-action-bar.end{flex:none;padding-right:var(--sci-workbench-part-bar-actions-padding-inline)}:host>wb-view-list-button{flex:none}:host:before{content:\"\";position:absolute;bottom:0;left:0;right:0;height:1px;background-color:var(--sci-workbench-tab-border-color)}:host>div.tab-corner-radius{position:absolute;visibility:hidden;width:var(--sci-workbench-tab-border-radius)}:host>div.padding-inline{position:absolute;visibility:hidden;width:var(--sci-workbench-part-bar-padding-inline)}:host.on-drag-enter:not(.on-drag-start) wb-view-tab,:host.on-drag-enter:not(.on-drag-start) div.divider,:host.drag-over wb-view-tab,:host.drag-over div.divider,:host.on-drag-leave wb-view-tab,:host.on-drag-leave div.divider{transition:transform 175ms cubic-bezier(0,0,.2,1)}:host.on-drag-enter:not(.on-drag-start) div.drag-placeholder,:host.on-drag-leave div.drag-placeholder{transition:width 175ms cubic-bezier(0,0,.2,1)}:host:not(:has(wb-view-tab.drag-source)):not(:has(wb-view-tab.drop-target)):not(.drag-over) div.drag-placeholder{display:none}:host.pointer-events-disabled>sci-viewport.tabbar::part(content){pointer-events:none}\n"], dependencies: [{ kind: "component", type: SciViewportComponent, selector: "sci-viewport", inputs: ["scrollbarStyle"], outputs: ["scroll"] }, { kind: "component", type: ViewTabComponent, selector: "wb-view-tab", inputs: ["viewId"] }, { kind: "component", type: PartActionBarComponent, selector: "wb-part-action-bar", inputs: ["actions"] }, { kind: "component", type: ViewListButtonComponent, selector: "wb-view-list-button" }] }); }
418
515
  }
419
516
  i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.0.2", ngImport: i0, type: PartBarComponent, decorators: [{
420
517
  type: Component,
421
518
  args: [{ selector: 'wb-part-bar', standalone: true, imports: [
422
- NgFor,
423
- AsyncPipe,
424
519
  SciViewportComponent,
425
- SciDimensionModule,
426
520
  ViewTabComponent,
427
521
  PartActionBarComponent,
428
522
  ViewListButtonComponent,
429
- NgIf,
430
- ], template: "<sci-viewport class=\"tabbar\" scrollbarStyle=\"hidden\"\n [class.dragover]=\"dragover$ | async\"\n sciDimension (sciDimensionChange)=\"onTabbarViewportDimensionChange()\"\n (scroll)=\"onScroll()\">\n <ng-container *ngFor=\"let viewId of viewIds$ | async;\">\n <div class=\"divider\" *ngIf=\"viewtab === dropTargetViewTab\"></div>\n <wb-view-tab #viewtab\n [viewId]=\"viewId\"\n [class.drag-source]=\"viewtab === dragSourceViewTab\"\n [class.drop-target]=\"viewtab === dropTargetViewTab\">\n </wb-view-tab>\n <div class=\"divider\"></div>\n </ng-container>\n\n <!-- Placeholder element to grow the viewport to fit the drag image. -->\n <div class=\"drag-image-placeholder\"></div>\n</sci-viewport>\n<wb-part-action-bar/>\n<wb-view-list-button/>\n\n<!-- Element for injecting the corner radius into the component. -->\n<div class=\"tab-corner-radius\" #tab_corner_radius></div>\n<!-- Element for injecting the tabbar padding into the component. -->\n<div class=\"padding-inline\" #padding_inline></div>\n", styles: ["@charset \"UTF-8\";:host{--\\275part-bar-indent-left: 0;--\\275part-bar-indent-right: 0;--\\275part-bar-drag-source-width: 0;--\\275part-bar-drag-image-placeholder-width: 0;display:flex;color:var(--sci-workbench-tab-text-color);background-color:var(--sci-workbench-part-bar-background-color);border-top:var(--sci-workbench-part-bar-padding-top) solid transparent;background-clip:border-box;height:var(--sci-workbench-tab-height);box-sizing:content-box;position:relative;container-name:viewtab;container-type:size}wb-workbench:has(wb-main-area-layout) wb-part:not(.main-area) :host{background-color:var(--sci-workbench-part-peripheral-bar-background-color)}:host>sci-viewport.tabbar{flex:initial}:host>sci-viewport.tabbar::part(content){display:flex;padding-left:var(--\\275part-bar-indent-left);padding-right:var(--\\275part-bar-indent-right)}:host>sci-viewport.tabbar:not(.dragover):not(:has(wb-view-tab:not(.drag-source)))::part(content){padding-right:0}:host>sci-viewport.tabbar>wb-view-tab{flex:none}:host>sci-viewport.tabbar>wb-view-tab.drag-source{display:none}:host>sci-viewport.tabbar>div.divider{flex:none;display:flex;position:relative;width:0}:host>sci-viewport.tabbar>div.divider:after{flex:none;align-self:center;content:\"\";position:absolute;width:1px;left:-1px;height:65%;background-color:var(--sci-workbench-part-bar-divider-color)}:host>sci-viewport.tabbar>div.drag-image-placeholder{flex:none;width:var(--\\275part-bar-drag-image-placeholder-width)}:host>sci-viewport.tabbar>wb-view-tab.drop-target,:host>sci-viewport.tabbar wb-view-tab.drop-target~:is(wb-view-tab,div.divider),:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drop-target){transform:translate(var(--\\275part-bar-drag-source-width))}:host>sci-viewport.tabbar>wb-view-tab:is(.active,.drag-source)+div.divider{display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.active:not(.drag-source)){display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drag-source:not(.active)){display:none}:host>wb-part-action-bar{flex:auto}:host>wb-view-list-button{flex:none}:host:before{content:\"\";position:absolute;bottom:0;left:0;right:0;height:1px;background-color:var(--sci-workbench-tab-border-color)}:host>div.tab-corner-radius{position:absolute;visibility:hidden;width:var(--sci-workbench-tab-border-radius)}:host>div.padding-inline{position:absolute;visibility:hidden;width:var(--sci-workbench-part-bar-padding-inline)}:host:not(.calculating-max-viewport-width).drag-enter wb-view-tab,:host:not(.calculating-max-viewport-width).drag-enter div.divider,:host:not(.calculating-max-viewport-width).drag-over wb-view-tab,:host:not(.calculating-max-viewport-width).drag-over div.divider,:host:not(.calculating-max-viewport-width).drag-leave wb-view-tab,:host:not(.calculating-max-viewport-width).drag-leave div.divider{transition:transform 175ms cubic-bezier(0,0,.2,1)}:host:not(.calculating-max-viewport-width).drag-enter div.drag-image-placeholder,:host:not(.calculating-max-viewport-width).drag-leave div.drag-image-placeholder{transition:width 175ms cubic-bezier(0,0,.2,1)}\n"] }]
431
- }], ctorParameters: () => [{ type: i0.ElementRef }, { type: undefined, decorators: [{
432
- type: Inject,
433
- args: [WORKBENCH_ID]
434
- }] }, { type: i1.WorkbenchLayoutService }, { type: i2.ɵWorkbenchRouter }, { type: i3.ViewTabDragImageRenderer }, { type: i4.ɵWorkbenchPart }, { type: i5.ViewDragService }, { type: i0.DestroyRef }, { type: i0.NgZone }], propDecorators: { _viewportElement: [{
435
- type: ViewChild,
436
- args: [SciViewportComponent, { static: true, read: ElementRef }]
437
- }], _viewportComponent: [{
438
- type: ViewChild,
439
- args: [SciViewportComponent, { static: true }]
440
- }], _tabCornerRadiusElement: [{
441
- type: ViewChild,
442
- args: ['tab_corner_radius', { static: true }]
443
- }], _paddingInlineElement: [{
444
- type: ViewChild,
445
- args: ['padding_inline', { static: true }]
446
- }], injectViewTabs: [{
447
- type: ViewChildren,
448
- args: [ViewTabComponent]
449
- }], onDoubleClick: [{
523
+ ], template: "<sci-viewport class=\"tabbar e2e-tabbar\" scrollbarStyle=\"hidden\">\n @for (viewId of part.viewIds(); track viewId) {\n @if (viewtab === dropTargetViewTab()) {\n <div class=\"divider\"></div>\n }\n <wb-view-tab #viewtab\n [viewId]=\"viewId\"\n [class.drag-source]=\"viewtab === dragSourceViewTab()\"\n [class.drop-target]=\"viewtab === dropTargetViewTab()\"/>\n <div class=\"divider\"></div>\n }\n\n <!-- Placeholder for expanding the viewport when dragging a tab to the right, moving part actions along with the dragover event. -->\n <div class=\"drag-placeholder\"></div>\n</sci-viewport>\n\n<!-- Actions -->\n@if (startActions().length) {\n <wb-part-action-bar [actions]=\"startActions()\" class=\"start\"/>\n}\n<div class=\"filler\" #filler></div>\n@if (endActions().length) {\n <wb-part-action-bar [actions]=\"endActions()\" class=\"end\"/>\n}\n\n<!-- View List Dropdown -->\n<wb-view-list-button/>\n\n<!-- Element for injecting the corner radius into the component. -->\n<div class=\"tab-corner-radius\" #tab_corner_radius></div>\n<!-- Element for injecting the tabbar padding into the component. -->\n<div class=\"padding-inline\" #padding_inline></div>\n", styles: ["@charset \"UTF-8\";:host{--\\275part-bar-indent-left: 0;--\\275part-bar-indent-right: 0;--\\275part-bar-drag-source-width: 0;--\\275part-bar-drag-placeholder-width: 0;display:flex;color:var(--sci-workbench-tab-text-color);background-color:var(--sci-workbench-part-bar-background-color);border-top:var(--sci-workbench-part-bar-padding-top) solid transparent;background-clip:border-box;height:var(--sci-workbench-tab-height);box-sizing:content-box;position:relative;container-name:viewtab;container-type:size}wb-workbench:has(wb-main-area-layout) wb-part:not(.main-area) :host{background-color:var(--sci-workbench-part-peripheral-bar-background-color)}:host>sci-viewport.tabbar{flex:initial}:host>sci-viewport.tabbar::part(content){display:flex;padding-left:var(--\\275part-bar-indent-left);padding-right:var(--\\275part-bar-indent-right)}:host>sci-viewport.tabbar>wb-view-tab{flex:none}:host>sci-viewport.tabbar>wb-view-tab.drag-source{display:none}:host>sci-viewport.tabbar>div.divider{flex:none;display:flex;position:relative;width:0}:host>sci-viewport.tabbar>div.divider:after{flex:none;align-self:center;content:\"\";position:absolute;width:1px;left:-1px;height:65%;background-color:var(--sci-workbench-part-bar-divider-color)}:host>sci-viewport.tabbar>div.drag-placeholder{flex:none;width:var(--\\275part-bar-drag-placeholder-width)}:host>sci-viewport.tabbar>wb-view-tab.drop-target,:host>sci-viewport.tabbar wb-view-tab.drop-target~:is(wb-view-tab,div.divider),:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drop-target){transform:translate(var(--\\275part-bar-drag-source-width))}:host>sci-viewport.tabbar>wb-view-tab:is(.active,.drag-source)+div.divider{display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.active:not(.drag-source)){display:none}:host>sci-viewport.tabbar>div.divider:has(+wb-view-tab.drag-source:not(.active)){display:none}:host:not(.drag-over)>sci-viewport.tabbar:not(:has(wb-view-tab:not(.drag-source)))::part(content){padding-right:0}:host>wb-part-action-bar.start{flex:none;padding-left:var(--sci-workbench-part-bar-actions-padding-inline)}:host>div.filler{flex:auto}:host>wb-part-action-bar.end{flex:none;padding-right:var(--sci-workbench-part-bar-actions-padding-inline)}:host>wb-view-list-button{flex:none}:host:before{content:\"\";position:absolute;bottom:0;left:0;right:0;height:1px;background-color:var(--sci-workbench-tab-border-color)}:host>div.tab-corner-radius{position:absolute;visibility:hidden;width:var(--sci-workbench-tab-border-radius)}:host>div.padding-inline{position:absolute;visibility:hidden;width:var(--sci-workbench-part-bar-padding-inline)}:host.on-drag-enter:not(.on-drag-start) wb-view-tab,:host.on-drag-enter:not(.on-drag-start) div.divider,:host.drag-over wb-view-tab,:host.drag-over div.divider,:host.on-drag-leave wb-view-tab,:host.on-drag-leave div.divider{transition:transform 175ms cubic-bezier(0,0,.2,1)}:host.on-drag-enter:not(.on-drag-start) div.drag-placeholder,:host.on-drag-leave div.drag-placeholder{transition:width 175ms cubic-bezier(0,0,.2,1)}:host:not(:has(wb-view-tab.drag-source)):not(:has(wb-view-tab.drop-target)):not(.drag-over) div.drag-placeholder{display:none}:host.pointer-events-disabled>sci-viewport.tabbar::part(content){pointer-events:none}\n"] }]
524
+ }], ctorParameters: () => [], propDecorators: { onDoubleClick: [{
450
525
  type: HostListener,
451
526
  args: ['dblclick', ['$event']]
452
- }], onViewDragStart: [{
453
- type: HostListener,
454
- args: ['dragstart', ['$event']]
455
- }], onViewDragEnd: [{
456
- type: HostListener,
457
- args: ['dragend']
458
527
  }] } });
459
- //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFydC1iYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2Npb24vd29ya2JlbmNoL3NyYy9saWIvcGFydC9wYXJ0LWJhci9wYXJ0LWJhci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zY2lvbi93b3JrYmVuY2gvc3JjL2xpYi9wYXJ0L3BhcnQtYmFyL3BhcnQtYmFyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQUFDLFNBQVMsRUFBYyxVQUFVLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFBNkIsU0FBUyxFQUFFLFlBQVksRUFBQyxNQUFNLGVBQWUsQ0FBQztBQUMxSSxPQUFPLEVBQUMsZ0JBQWdCLEVBQUMsTUFBTSxnQ0FBZ0MsQ0FBQztBQUVoRSxPQUFPLEVBQUMsTUFBTSxFQUFFLEdBQUcsRUFBRSxRQUFRLEVBQUUsU0FBUyxFQUFFLFNBQVMsRUFBRSxJQUFJLEVBQUUsU0FBUyxFQUFDLE1BQU0sZ0JBQWdCLENBQUM7QUFDNUYsT0FBTyxFQUFDLHVCQUF1QixFQUFFLGVBQWUsRUFBRSxhQUFhLEVBQUUsY0FBYyxFQUFFLElBQUksRUFBRSxRQUFRLEVBQWMsT0FBTyxFQUFDLE1BQU0sTUFBTSxDQUFDO0FBQ2xJLE9BQU8sRUFBYyxpQkFBaUIsRUFBMkIsTUFBTSxxREFBcUQsQ0FBQztBQUU3SCxPQUFPLEVBQUMsaUJBQWlCLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUV0SCxPQUFPLEVBQUMsV0FBVyxFQUFFLFFBQVEsRUFBRSxhQUFhLEVBQUUsZUFBZSxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDL0YsT0FBTyxFQUFDLG9CQUFvQixFQUFDLE1BQU0sNEJBQTRCLENBQUM7QUFFaEUsT0FB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a0I7d0JBQ2xCLGdCQUFnQjt3QkFDaEIsc0JBQXNCO3dCQUN0Qix1QkFBdUI7d0JBQ3ZCLElBQUk7cUJBQ0w7OzBCQXdFWSxNQUFNOzJCQUFDLFlBQVk7NlBBM0R4QixnQkFBZ0I7c0JBRHZCLFNBQVM7dUJBQUMsb0JBQW9CLEVBQUUsRUFBQyxNQUFNLEVBQUUsSUFBSSxFQUFFLElBQUksRUFBRSxVQUFVLEVBQUM7Z0JBSXpELGtCQUFrQjtzQkFEekIsU0FBUzt1QkFBQyxvQkFBb0IsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUM7Z0JBSXZDLHVCQUF1QjtzQkFEOUIsU0FBUzt1QkFBQyxtQkFBbUIsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUM7Z0JBSXRDLHFCQUFxQjtzQkFENUIsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFDLE1BQU0sRUFBRSxJQUFJLEVBQUM7Z0JBSWhDLGNBQWM7c0JBRHhCLFlBQVk7dUJBQUMsZ0JBQWdCO2dCQXFFdkIsYUFBYTtzQkFEbkIsWUFBWTt1QkFBQyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQUM7Z0JBd0I3QixlQUFlO3NCQURyQixZQUFZO3VCQUFDLFdBQVcsRUFBRSxDQUFDLFFBQVEsQ0FBQztnQkE4QzlCLGFBQWE7c0JBRG5CLFlBQVk7dUJBQUMsU0FBUyIsInNvdXJjZXNDb250ZW50IjpbIi8qXG4gKiBDb3B5cmlnaHQgKGMpIDIwMTgtMjAyMyBTd2lzcyBGZWRlcmFsIFJhaWx3YXlzXG4gKlxuICogVGhpcyBwcm9ncmFtIGFuZCB0aGUgYWNjb21wYW55aW5nIG1hdGVyaWFscyBhcmUgbWFkZVxuICogYXZhaWxhYmxlIHVuZGVyIHRoZSB0ZXJtcyBvZiB0aGUgRWNsaXBzZSBQdWJsaWMgTGljZW5zZSAyLjBcbiAqIHdoaWNoIGlzIGF2YWlsYWJsZSBhdCBodHRwczovL3d3dy5lY2xpcHNlLm9yZy9sZWdhbC9lcGwtMi4wL1xuICpcbiAqIFNQRFgtTGljZW5zZS1JZGVudGlmaWVyOiBFUEwtMi4wXG4gKi9cblxuaW1wb3J0IHtDb21wb25lbnQsIERlc3Ryb3lSZWYsIEVsZW1lbnRSZWYsIEhvc3RMaXN0ZW5lciwgSW5qZWN0LCBOZ1pvbmUsIE9uSW5pdCwgUXVlcnlMaXN0LCBWaWV3Q2hpbGQsIFZpZXdDaGlsZHJlbn0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQge1ZpZXdUYWJDb21wb25lbnR9IGZyb20gJy4uL3ZpZXctdGFiL3ZpZXctdGFiLmNvbXBvbmVudCc7XG5pbXBvcnQge1dvcmtiZW5jaExheW91dFNlcnZpY2V9IGZyb20gJy4uLy4uL2xheW91dC93b3JrYmVuY2gtbGF5b3V0LnNlcnZpY2UnO1xuaW1wb3J0IHtmaWx0ZXIsIG1hcCwgbWVyZ2VNYXAsIHN0YXJ0V2l0aCwgc3dpdGNoTWFwLCB0YWtlLCB0YWtlVW50aWx9IGZyb20gJ3J4anMvb3BlcmF0b3JzJztcbmltcG9ydCB7YW5pbWF0aW9uRnJhbWVTY2hlZHVsZXIsIEJlaGF2aW9yU3ViamVjdCwgY29tYmluZUxhdGVzdCwgZmlyc3RWYWx1ZUZyb20sIGZyb20sIGludGVydmFsLCBPYnNlcnZhYmxlLCBTdWJqZWN0fSBmcm9tICdyeGpzJztcbmltcG9ydCB7Q29uc3RyYWluRm4sIFZpZXdEcmFnSW1hZ2VSZWN0LCBWaWV3VGFiRHJhZ0ltYWdlUmVuZGVyZXJ9IGZyb20gJy4uLy4uL3ZpZXctZG5kL3ZpZXctdGFiLWRyYWctaW1hZ2UtcmVuZGVyZXIuc2VydmljZSc7XG5pbXBvcnQge1ZpZXdEcmFnRGF0YSwgVmlld0RyYWdTZXJ2aWNlfSBmcm9tICcuLi8uLi92aWV3LWRuZC92aWV3LWRyYWcuc2VydmljZSc7XG5pbXBvcnQge2dldENzc1RyYW5zbGF0aW9uLCBzZXRDc3NDbGFzcywgc2V0Q3NzVmFyaWFibGUsIHVuc2V0Q3NzQ2xhc3MsIHVuc2V0Q3NzVmFyaWFibGV9IGZyb20gJy4uLy4uL2NvbW1vbi9kb20udXRpbCc7XG5pbXBvcnQge8m1V29ya2JlbmNoUGFydH0gZnJvbSAnLi4vybV3b3JrYmVuY2gtcGFydC5tb2RlbCc7XG5pbXBvcnQge2ZpbHRlckFycmF5LCBtYXBBcnJheSwgb2JzZXJ2ZUluc2lkZSwgc3Vic2NyaWJlSW5zaWRlfSBmcm9tICdAc2Npb24vdG9vbGtpdC9vcGVyYXRvcnMnO1xuaW1wb3J0IHtTY2lWaWV3cG9ydENvbXBvbmVudH0gZnJvbSAnQHNjaW9uL2NvbXBvbmVudHMvdmlld3BvcnQnO1xuaW1wb3J0IHvJtVdvcmtiZW5jaFJvdXRlcn0gZnJvbSAnLi4vLi4vcm91dGluZy/JtXdvcmtiZW5jaC1yb3V0ZXIuc2VydmljZSc7XG5pbXBvcnQge1NjaURpbWVuc2lvbk1vZHVsZX0gZnJvbSAnQHNjaW9uL2NvbXBvbmVudHMvZGltZW5zaW9uJztcbmltcG9ydCB7QXN5bmNQaXBlLCBOZ0ZvciwgTmdJZn0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7UGFydEFjdGlvbkJhckNvbXBvbmVudH0gZnJvbSAnLi4vcGFydC1hY3Rpb24tYmFyL3BhcnQtYWN0aW9uLWJhci5jb21wb25lbnQnO1xuaW1wb3J0IHtWaWV3TGlzdEJ1dHRvbkNvbXBvbmVudH0gZnJvbSAnLi4vdmlldy1saXN0LWJ1dHRvbi92aWV3LWxpc3QtYnV0dG9uLmNvbXBvbmVudCc7XG5pbXBvcnQge3Rha2VVbnRpbERlc3Ryb3llZH0gZnJvbSAnQGFuZ3VsYXIvY29yZS9yeGpzLWludGVyb3AnO1xuaW1wb3J0IHtmcm9tRGltZW5zaW9uJH0gZnJvbSAnQHNjaW9uL3Rvb2xraXQvb2JzZXJ2YWJsZSc7XG5pbXBvcnQge1dPUktCRU5DSF9JRH0gZnJvbSAnLi4vLi4vd29ya2JlbmNoLWlkJztcbmltcG9ydCB7Vmlld0lkfSBmcm9tICcuLi8uLi92aWV3L3dvcmtiZW5jaC12aWV3Lm1vZGVsJztcblxuLyoqXG4gKiBSZW5kZXJzIHZpZXcgdGFicyBhbmQgYWN0aW9ucyBvZiBhIHtAbGluayBXb3JrYmVuY2hQYXJ0fS5cbiAqXG4gKiBUYWJzIGFyZSBhZGRlZCB0byBhIHZpZXdwb3J0LCB3aGljaCB0aGUgdXNlciBjYW4gc2Nyb2xsIGlmIG5vdCBlbm91Z2ggc3BhY2UuIFRoZSB2aWV3cG9ydCBncm93cyB3aXRoIGl0cyB0YWJzLFxuICogYWxsb3dpbmcgYWN0aW9ucyB0byBiZSBwbGFjZWQgZGlyZWN0bHkgYWZ0ZXIgdGhlIGxhc3QgdGFiIG9yIG9uIHRoZSByaWdodCBzaWRlLlxuICpcbiAqICMjIERyYWcgRXZlbnRzXG4gKiBXZSB1c2UgbmF0aXZlIGRyYWcgYW5kIGRyb3AgdG8gc3VwcG9ydCBkcmFnZ2luZyB2aWV3cyB0byBvdGhlciB3aW5kb3dzLlxuICpcbiAqIEJ5IGxpc3RlbmluZyB0byBkcmFnIGV2ZW50cywgdGhlIHRhYmJhciB2aXN1YWxpemVzIHRhYnMgZHVyaW5nIGEgZHJhZyBvcGVyYXRpb24uIFRoZSBkcmFnIG9wZXJhdGlvbiBpcyBpbml0aWF0ZWQgaW4ge0BsaW5rIFZpZXdUYWJDb21wb25lbnR9LlxuICogLSBgZHJhZ3N0YXJ0YCBhbmQgYGRyYWdlbmRgIGV2ZW50cyBhcmUgZmlyZWQgaW4gdGhlIHRhYmJhciB3aGVyZSB0aGUgZHJhZyBvcGVyYXRpb24gd2FzIGluaXRpYXRlZC5cbiAqIC0gYGRyYWdlbnRlcmAgZXZlbnQgaXMgZmlyZWQgd2hlbiBhIHRhYiBlbnRlcnMgdGhlIHRhYmJhci5cbiAqIC0gYGRyYWdvdmVyYCBldmVudHMgYXJlIGZpcmVkIHdoZW4gZHJhZ2dpbmcgYSB0YWIgb3ZlciB0aGUgdGFiYmFyLlxuICogLSBgZHJhZ2xlYXZlYCBldmVudCBpcyBmaXJlZCB3aGVuIGEgdGFiIGxlYXZlcyB0aGUgdGFiYmFyLlxuICogLSBgZHJvcGAgZXZlbnQgaXMgZmlyZWQgd2hlbiB0aGUgdXNlciBkcm9wcyBhIHRhYiBpbiB0aGUgdGFiYmFyLlxuICogLSBOb3RlIHRoYXQgYGRyYWdsZWF2ZWAgZXZlbnQgaXMgbm90IGZpcmVkIG9uIGRyb3AgYWN0aW9uLiBUaGVyZWZvcmUsIGFsd2F5cyBoYW5kbGUgYm90aCBldmVudHMsIGBkcmFnbGVhdmVgIGFuZCBgZHJvcGAgZXZlbnRzLCByZXNwZWN0aXZlbHkuXG4gKlxuICogIyMgVGVybWlub2xvZ3lcbiAqIC0gRHJhZyBzb3VyY2U6IFRhYiB0aGF0IGlzIGJlaW5nIGRyYWdnZWQuXG4gKiAtIERyb3AgdGFyZ2V0OiBUYWIgYmVmb3JlIHdoaWNoIHRvIGluc2VydCB0aGUgZHJhZyBzb3VyY2Ugb24gZHJvcCwgb3IgYGVuZGAgaWYgZHJvcHBpbmcgaXQgYWZ0ZXIgdGhlIGxhc3QgdGFiLlxuICogLSBEcmFnIGltYWdlOiAgSW1hZ2UgZm9yIHRoZSB0YWIgdG8gYmUgZHJhZ2dlZC4gV2UgZG8gbm90IHVzZSB0aGUgbmF0aXZlIGRyYWcgaW1hZ2Ugc3VwcG9ydCB0byBjb250cm9sIGRyYWcgaW1hZ2UgcG9zaXRpb24gYW5kIHNpemUsXG4gKiAgICAgICAgICAgICAgICBlLmcuLCB0byBzbmFwIHRoZSBkcmFnIGltYWdlIHRvIHRoZSB0YWJiYXIgd2hlbiBkcmFnZ2luZyBuZWFyIGl0LlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd3Yi1wYXJ0LWJhcicsXG4gIHRlbXBsYXRlVXJsOiAnLi9wYXJ0LWJhci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWycuL3BhcnQtYmFyLmNvbXBvbmVudC5zY3NzJ10sXG4gIHN0YW5kYWxvbmU6IHRydWUsXG4gIGltcG9ydHM6IFtcbiAgICBOZ0ZvcixcbiAgICBBc3luY1BpcGUsXG4gICAgU2NpVmlld3BvcnRDb21wb25lbnQsXG4gICAgU2NpRGltZW5zaW9uTW9kdWxlLFxuICAgIFZpZXdUYWJDb21wb25lbnQsXG4gICAgUGFydEFjdGlvbkJhckNvbXBvbmVudCxcbiAgICBWaWV3TGlzdEJ1dHRvbkNvbXBvbmVudCxcbiAgICBOZ0lmLFxuICBdLFxufSlcbmV4cG9ydCBjbGFzcyBQYXJ0QmFyQ29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0IHtcblxuICBwcml2YXRlIHJlYWRvbmx5IF9ob3N0OiBIVE1MRWxlbWVudDtcbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld3BvcnRDaGFuZ2UkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld1RhYnMkID0gbmV3IEJlaGF2aW9yU3ViamVjdDxWaWV3VGFiQ29tcG9uZW50W10+KFtdKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZHJhZ2VudGVyJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2RyYWdsZWF2ZSQgPSBuZXcgU3ViamVjdDx2b2lkPigpO1xuICBwcml2YXRlIHJlYWRvbmx5IF9kcmFnZW5kJCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XG4gIHB1YmxpYyByZWFkb25seSBkcmFnb3ZlciQ6IE9ic2VydmFibGU8Ym9vbGVhbj47XG5cbiAgQFZpZXdDaGlsZChTY2lWaWV3cG9ydENvbXBvbmVudCwge3N0YXRpYzogdHJ1ZSwgcmVhZDogRWxlbWVudFJlZn0pXG4gIHByaXZhdGUgX3ZpZXdwb3J0RWxlbWVudCE6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuXG4gIEBWaWV3Q2hpbGQoU2NpVmlld3BvcnRDb21wb25lbnQsIHtzdGF0aWM6IHRydWV9KVxuICBwcml2YXRlIF92aWV3cG9ydENvbXBvbmVudCE6IFNjaVZpZXdwb3J0Q29tcG9uZW50O1xuXG4gIEBWaWV3Q2hpbGQoJ3RhYl9jb3JuZXJfcmFkaXVzJywge3N0YXRpYzogdHJ1ZX0pXG4gIHByaXZhdGUgX3RhYkNvcm5lclJhZGl1c0VsZW1lbnQhOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50PjtcblxuICBAVmlld0NoaWxkKCdwYWRkaW5nX2lubGluZScsIHtzdGF0aWM6IHRydWV9KVxuICBwcml2YXRlIF9wYWRkaW5nSW5saW5lRWxlbWVudCE6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+O1xuXG4gIEBWaWV3Q2hpbGRyZW4oVmlld1RhYkNvbXBvbmVudClcbiAgcHVibGljIHNldCBpbmplY3RWaWV3VGFicyhxdWVyeUxpc3Q6IFF1ZXJ5TGlzdDxWaWV3VGFiQ29tcG9uZW50Pikge1xuICAgIHF1ZXJ5TGlzdC5jaGFuZ2VzXG4gICAgICAucGlwZShzdGFydFdpdGgocXVlcnlMaXN0KSwgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpKVxuICAgICAgLnN1YnNjcmliZShxdWVyeUxpc3QgPT4gdGhpcy5fdmlld1RhYnMkLm5leHQocXVlcnlMaXN0LnRvQXJyYXkoKSkpO1xuICB9XG5cbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgdGFiIGJlZm9yZSB3aGljaCB0byBpbnNlcnQgdGhlIGRyYWcgc291cmNlIG9uIGRyb3AsIG9yIGBlbmRgIGlmIGRyb3BwaW5nIGl0IGFmdGVyIHRoZSBsYXN0IHRhYi5cbiAgICovXG4gIHB1YmxpYyBkcm9wVGFyZ2V0Vmlld1RhYjogVmlld1RhYkNvbXBvbmVudCB8ICdlbmQnIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgdGFiIHdoZXJlIHRoZSBkcmFnIG9wZXJhdGlvbiB3YXMgc3RhcnRlZC5cbiAgICogVGhpcyByZWZlcmVuY2UgaXMgb25seSBzZXQgaWYgdGhlIGRyYWcgb3BlcmF0aW9uIHN0YXJ0ZWQgb24gYSB0YWIgb2YgdGhpcyB0YWJiYXIuXG4gICAqL1xuICBwdWJsaWMgZHJhZ1NvdXJjZVZpZXdUYWI6IFZpZXdUYWJDb21wb25lbnQgfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogVHJhbnNmZXIgZGF0YSBvZiB0aGUgdGFiIGJlaW5nIGRyYWdnZWQgb3ZlciB0aGlzIHRhYmJhci5cbiAgICovXG4gIHByaXZhdGUgX2RyYWdEYXRhOiBWaWV3RHJhZ0RhdGEgfCBudWxsID0gbnVsbDtcblxuICAvKipcbiAgICogRnVuY3Rpb24gZm9yIHNuYXBwaW5nIHRoZSBkcmFnIGltYWdlIHRvIHRoZSB0YWJiYXIgd2hlbiBkcmFnZ2luZyBuZWFyIGl0LlxuICAgKi9cbiAgcHJpdmF0ZSBfY29uc3RyYWluRm46IENvbnN0cmFpbkZuIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIFRhYmJhciBpbmRlbnRzIHdoZXJlIHRvIGRpc3BsYXkgdGhlIHJvdW5kZWQgYm90dG9tIGNvcm5lcnMgb2YgdGhlIGZpcnN0IGFuZCBsYXN0IHZpZXcgdGFiLlxuICAgKi9cbiAgcHJpdmF0ZSBfdGFiYmFySW5kZW50ID0ge1xuICAgIGxlZnQ6IDAsXG4gICAgcmlnaHQ6IDAsXG4gIH07XG5cbiAgLyoqXG4gICAqIE5vdGlmaWVzIHdoZW4gdGhlIGRyYWcgYW5pbWF0aW9uIGhhcyBmaW5pc2hlZCwgaS5lLiwgdGFicyBoYXZlIHRyYW5zaXRpb25lZCB0byB0aGVpciBmaW5hbCBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgX2RyYWdBbmltYXRpb25TdGFibGUkID0gaW50ZXJ2YWwoMCwgYW5pbWF0aW9uRnJhbWVTY2hlZHVsZXIpXG4gICAgLnBpcGUoXG4gICAgICBmaWx0ZXIoKCkgPT4gdGhpcy5pc0RyYWdBbmltYXRpb25TdGFibGUoKSksXG4gICAgICBzdWJzY3JpYmVJbnNpZGUoY29udGludWVGbiA9PiB0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKGNvbnRpbnVlRm4pKSxcbiAgICAgIG9ic2VydmVJbnNpZGUoY29udGludWVGbiA9PiB0aGlzLl96b25lLnJ1bihjb250aW51ZUZuKSksXG4gICAgICBtYXAoKCkgPT4gdW5kZWZpbmVkIGFzIHZvaWQpLFxuICAgICk7XG5cbiAgY29uc3RydWN0b3IoaG9zdDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD4sXG4gICAgICAgICAgICAgIEBJbmplY3QoV09SS0JFTkNIX0lEKSBwcml2YXRlIF93b3JrYmVuY2hJZDogc3RyaW5nLFxuICAgICAgICAgICAgICBwcml2YXRlIF93b3JrYmVuY2hMYXlvdXRTZXJ2aWNlOiBXb3JrYmVuY2hMYXlvdXRTZXJ2aWNlLFxuICAgICAgICAgICAgICBwcml2YXRlIF9yb3V0ZXI6IMm1V29ya2JlbmNoUm91dGVyLFxuICAgICAgICAgICAgICBwcml2YXRlIF92aWV3VGFiRHJhZ0ltYWdlUmVuZGVyZXI6IFZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlcixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfcGFydDogybVXb3JrYmVuY2hQYXJ0LFxuICAgICAgICAgICAgICBwcml2YXRlIF92aWV3RHJhZ1NlcnZpY2U6IFZpZXdEcmFnU2VydmljZSxcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfZGVzdHJveVJlZjogRGVzdHJveVJlZixcbiAgICAgICAgICAgICAgcHJpdmF0ZSBfem9uZTogTmdab25lKSB7XG4gICAgdGhpcy5faG9zdCA9IGhvc3QubmF0aXZlRWxlbWVudDtcbiAgICB0aGlzLmRyYWdvdmVyJCA9IHRoaXMuX3ZpZXdEcmFnU2VydmljZS50YWJiYXJEcmFnT3ZlciQucGlwZShtYXAocGFydElkID0+IHBhcnRJZCA9PT0gdGhpcy5fcGFydC5pZCkpO1xuICB9XG5cbiAgcHVibGljIG5nT25Jbml0KCk6IHZvaWQge1xuICAgIHRoaXMuaW5zdGFsbEFjdGl2ZVZpZXdTY3JvbGxlcigpO1xuICAgIHRoaXMuaW5zdGFsbFNjcm9sbGVkSW50b1ZpZXdVcGRhdGVyKCk7XG4gICAgdGhpcy5pbnN0YWxsVmlld0RyYWdMaXN0ZW5lcigpO1xuICAgIHRoaXMuaW5zdGFsbFRhYmJhckluZGVudFNpemVEZXRlY3RvcigpO1xuICAgIHRoaXMuaW5zdGFsbFZpZXdwb3J0Q2xpZW50U2l6ZURldGVjdG9yKCk7XG4gIH1cblxuICBASG9zdExpc3RlbmVyKCdkYmxjbGljaycsIFsnJGV2ZW50J10pXG4gIHB1YmxpYyBvbkRvdWJsZUNsaWNrKGV2ZW50OiBNb3VzZUV2ZW50KTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX3BhcnQuaXNJbk1haW5BcmVhKSB7XG4gICAgICB0aGlzLl9yb3V0ZXIubmF2aWdhdGUobGF5b3V0ID0+IGxheW91dC50b2dnbGVNYXhpbWl6ZWQoKSkudGhlbigpO1xuICAgIH1cbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIHB1YmxpYyBnZXQgdmlld0lkcyQoKTogT2JzZXJ2YWJsZTxWaWV3SWRbXT4ge1xuICAgIHJldHVybiB0aGlzLl9wYXJ0LnZpZXdJZHMkO1xuICB9XG5cbiAgcHVibGljIG9uVGFiYmFyVmlld3BvcnREaW1lbnNpb25DaGFuZ2UoKTogdm9pZCB7XG4gICAgdGhpcy5fdmlld3BvcnRDaGFuZ2UkLm5leHQoKTtcbiAgfVxuXG4gIHB1YmxpYyBvblNjcm9sbCgpOiB2b2lkIHtcbiAgICB0aGlzLl92aWV3cG9ydENoYW5nZSQubmV4dCgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgc3RhcnRzIGRyYWdnaW5nIGEgdGFiIG9mIHRoaXMgdGFiYmFyLlxuICAgKi9cbiAgQEhvc3RMaXN0ZW5lcignZHJhZ3N0YXJ0JywgWyckZXZlbnQnXSlcbiAgcHVibGljIG9uVmlld0RyYWdTdGFydChldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XG4gICAgaWYgKCF0aGlzLl92aWV3RHJhZ1NlcnZpY2UuaXNWaWV3RHJhZ0V2ZW50KGV2ZW50KSkge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGNvbnN0IGRyYWdEYXRhID0gdGhpcy5fdmlld0RyYWdTZXJ2aWNlLnZpZXdEcmFnRGF0YSE7XG4gICAgY29uc3QgZHJhZ1NvdXJjZUluZGV4ID0gdGhpcy5fdmlld1RhYnMuZmluZEluZGV4KHZpZXdUYWIgPT4gdmlld1RhYi52aWV3SWQgPT09IGRyYWdEYXRhLnZpZXdJZCk7XG4gICAgY29uc3QgZHJhZ1NvdXJjZVZpZXdUYWIgPSB0aGlzLl92aWV3VGFic1tkcmFnU291cmNlSW5kZXhdO1xuICAgIGNvbnN0IGRyb3BUYXJnZXRWaWV3VGFiID0gdGhpcy5fdmlld1RhYnNbZHJhZ1NvdXJjZUluZGV4ICsgMV0gPz8gJ2VuZCc7XG5cbiAgICAvLyBDb25zdHJhaW4gZnVuY3Rpb24gZm9yIHNuYXBwaW5nIHRoZSBkcmFnIGltYWdlIHRvIHRoZSB0YWJiYXIgd2hlbiBkcmFnZ2luZyBuZWFyIGl0LlxuICAgIHRoaXMuX2NvbnN0cmFpbkZuID0gdGhpcy5jcmVhdGVEcmFnSW1hZ2VDb25zdHJhaW5GbigpO1xuICAgIHRoaXMuX3ZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlci5zZXRDb25zdHJhaW5EcmFnSW1hZ2VSZWN0Rm4odGhpcy5fY29uc3RyYWluRm4pO1xuICAgIHRoaXMuX3ZpZXdEcmFnU2VydmljZS5zZXRUYWJiYXJEcmFnb3Zlcih0aGlzLl9wYXJ0LmlkKTtcblxuICAgIC8vIFdoZW4gc3RhcnQgZHJhZ2dpbmcgYSB2aWV3IHRhYiwgd2UgcmVtb3ZlIGl0IGZyb20gdGhlIHRhYmJhciBieSBzZXR0aW5nIGl0cyBgZGlzcGxheWAgdG8gYG5vbmVgIGFuZCByZW5kZXIgaXRzIGRyYWcgaW1hZ2UgaW4gYFZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlcmAgaW5zdGVhZC5cbiAgICAvLyBIb3dldmVyLCBkbyBub3QgdW5zZXQgdGhlIGBkaXNwbGF5YCBvZiB0aGUgZHJhZyBzb3VyY2UgZHVyaW5nIGBkcmFnc3RhcnRgLiBPdGhlcndpc2UsIHRoZSBuYXRpdmUgZHJhZyBvcGVyYXRpb24gd291bGQgYmUgY29ycnVwdGVkIGluIENocm9tZSBhbmQgRWRnZSAoYnV0IG5vdCBpbiBGaXJlZm94KS5cbiAgICBhbmltYXRpb25GcmFtZVNjaGVkdWxlci5zY2hlZHVsZSgoKSA9PiB7XG4gICAgICB0aGlzLmRyYWdTb3VyY2VWaWV3VGFiID0gZHJhZ1NvdXJjZVZpZXdUYWI7XG4gICAgICB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiID0gZHJvcFRhcmdldFZpZXdUYWI7IC8vIFNldCBkcm9wIHRhcmdldCB0byBhdm9pZCB0YWIgYW5pbWF0aW9uLlxuICAgICAgc2V0Q3NzVmFyaWFibGUodGhpcy5faG9zdCwge1xuICAgICAgICAnLS3JtXBhcnQtYmFyLWRyYWctc291cmNlLXdpZHRoJzogYCR7ZHJhZ0RhdGEudmlld1RhYldpZHRofXB4YCxcbiAgICAgICAgJy0tybVwYXJ0LWJhci1kcmFnLWltYWdlLXBsYWNlaG9sZGVyLXdpZHRoJzogYCR7ZHJhZ0RhdGEudmlld1RhYldpZHRofXB4YCxcbiAgICAgIH0pO1xuICAgIH0pO1xuXG4gICAgLy8gV2hlbiBkcmFnZ2luZyBhIHRhYiB2ZXJ5IHF1aWNrbHkgb3V0IG9mIHRoaXMgdGFiYmFyLCBvbmx5IHRoZSBgZHJhZ3N0YXJ0YCBldmVudCBnZXRzIGZpcmVkLCBidXQgbm90IHRoZSBgZHJhZ2VudGVyYCBldmVudC5cbiAgICAvLyBUaGVyZWZvcmUsIHdlIHN1YnNjcmliZSB0byBnbG9iYWwgYGRyYWdlbnRlcmAgZXZlbnRzIGFuZCBtYW51YWxseSBpbnZva2UgYG9uVGFiYmFyRHJhZ0xlYXZlYCB0byBjb3JyZWN0bHkgZGlzcGxheSB0aGUgdGFicyBhbmQgdGhlIGFjdGl2ZSB2aWV3LlxuICAgIHRoaXMuX3ZpZXdEcmFnU2VydmljZS52aWV3RHJhZyQod2luZG93LCB7ZXZlbnRUeXBlOiBbJ2RyYWdlbnRlciddfSlcbiAgICAgIC5waXBlKHRha2UoMSksIHRha2VVbnRpbCh0aGlzLl9kcmFnZW5kJCksIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoZXZlbnQgPT4ge1xuICAgICAgICAvLyBDaGVjayBpZiB0aGUgdXNlciBjb250aW51ZXMgZHJhZ2dpbmcgb3ZlciB0aGlzIHRhYmJhci5cbiAgICAgICAgLy8gSWYgbm90LCB0aGUgdXNlciBoYXMgcXVpY2tseSBkcmFnZ2VkIHRoZSB0YWIgb3V0IG9mIHRoZSB0YWJiYXIgYW5kIHdlICBtYW51YWxseSBjYWxsIGBvblRhYmJhckRyYWdMZWF2ZWAuXG4gICAgICAgIGlmICgodGhpcy5faG9zdC5jb21wYXJlRG9jdW1lbnRQb3NpdGlvbihldmVudC50YXJnZXQgYXMgRWxlbWVudCkgJiBOb2RlLkRPQ1VNRU5UX1BPU0lUSU9OX0NPTlRBSU5FRF9CWSkgPT09IDApIHtcbiAgICAgICAgICB0aGlzLm9uVGFiYmFyRHJhZ0xlYXZlKCk7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgZW5kcyBkcmFnZ2luZyBhIHRhYiBvZiB0aGlzIHRhYmJhci5cbiAgICpcbiAgICogSW52b2tlZCBvbmx5IGluIHRoZSB0YWJiYXIgd2hlcmUgdGhlIGRyYWcgb3BlcmF0aW9uIHN0YXJ0ZWQsIHJlZ2FyZGxlc3Mgb2Ygd2hldGhlciB0aGUgZHJhZyBvcGVyYXRpb24gd2FzIGNvbXBsZXRlZCBvciBjYW5jZWxlZC5cbiAgICovXG4gIEBIb3N0TGlzdGVuZXIoJ2RyYWdlbmQnKVxuICBwdWJsaWMgb25WaWV3RHJhZ0VuZCgpOiB2b2lkIHtcbiAgICB0aGlzLl9kcmFnZW5kJC5uZXh0KCk7XG4gICAgdGhpcy51bnNldERyYWdTdGF0ZSgpO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgZHJhZ3MgYSB0YWIgaW50byB0aGlzIHRhYmJhci5cbiAgICovXG4gIHByaXZhdGUgb25UYWJiYXJEcmFnRW50ZXIoZXZlbnQ6IERyYWdFdmVudCk6IHZvaWQge1xuICAgIHRoaXMuX2RyYWdlbnRlciQubmV4dCgpO1xuICAgIHRoaXMuX3ZpZXdEcmFnU2VydmljZS5zZXRUYWJiYXJEcmFnb3Zlcih0aGlzLl9wYXJ0LmlkKTtcbiAgICB0aGlzLl9kcmFnRGF0YSA9IHRoaXMuX3ZpZXdEcmFnU2VydmljZS52aWV3RHJhZ0RhdGEhO1xuXG4gICAgLy8gQ29uc3RyYWluIGZ1bmN0aW9uIGZvciBzbmFwcGluZyB0aGUgZHJhZyBpbWFnZSB0byB0aGUgdGFiYmFyIHdoZW4gZHJhZ2dpbmcgbmVhciBpdC5cbiAgICBpZiAoIXRoaXMuX2NvbnN0cmFpbkZuKSB7XG4gICAgICB0aGlzLl9jb25zdHJhaW5GbiA9IHRoaXMuY3JlYXRlRHJhZ0ltYWdlQ29uc3RyYWluRm4oKTtcbiAgICAgIHRoaXMuX3ZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlci5zZXRDb25zdHJhaW5EcmFnSW1hZ2VSZWN0Rm4odGhpcy5fY29uc3RyYWluRm4pO1xuICAgIH1cblxuICAgIC8vIExvY2F0ZSBkcm9wIHRhcmdldCB0byBoYXZlIGEgbmljZSBhbmltYXRpb24gZm9yIHRoZSBkcmFnIHNvdXJjZSBwbGFjZWhvbGRlci5cbiAgICB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiID0gdGhpcy5jb21wdXRlRHJvcFRhcmdldChldmVudCk7XG5cbiAgICAvLyBTZXQgdGhlIENTUyBjbGFzcyAnZHJhZy1lbnRlcicgdG8gaW5kaWNhdGUgZW50ZXJpbmcgdGhlIHRhYmJhci5cbiAgICBzZXRDc3NDbGFzcyh0aGlzLl9ob3N0LCAnZHJhZy1lbnRlcicsICdkcmFnLW92ZXInKTtcbiAgICB0aGlzLl9kcmFnQW5pbWF0aW9uU3RhYmxlJFxuICAgICAgLnBpcGUodGFrZSgxKSwgdGFrZVVudGlsKHRoaXMuX2RyYWdlbnRlciQpLCB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKHtjb21wbGV0ZTogKCkgPT4gdW5zZXRDc3NDbGFzcyh0aGlzLl9ob3N0LCAnZHJhZy1lbnRlcicpfSk7XG5cbiAgICBzZXRDc3NWYXJpYWJsZSh0aGlzLl9ob3N0LCB7XG4gICAgICAnLS3JtXBhcnQtYmFyLWRyYWctc291cmNlLXdpZHRoJzogYCR7dGhpcy5fZHJhZ0RhdGEudmlld1RhYldpZHRofXB4YCxcbiAgICAgICctLcm1cGFydC1iYXItZHJhZy1pbWFnZS1wbGFjZWhvbGRlci13aWR0aCc6IGAke3RoaXMuX2RyYWdEYXRhLnZpZXdUYWJXaWR0aH1weGAsXG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGludm9rZWQgd2hlbiB0aGUgdXNlciBkcmFncyBhIHRhYiBvdXQgb2YgdGhpcyB0YWJiYXIuXG4gICAqL1xuICBwcml2YXRlIG9uVGFiYmFyRHJhZ0xlYXZlKCk6IHZvaWQge1xuICAgIHRoaXMuX2RyYWdsZWF2ZSQubmV4dCgpO1xuXG4gICAgLy8gU2V0IHRoZSBDU1MgY2xhc3MgJ2RyYWctbGVhdmUnIHRvIGluZGljYXRlIGxlYXZpbmcgdGhlIHRhYmJhci5cbiAgICBzZXRDc3NDbGFzcyh0aGlzLl9ob3N0LCAnZHJhZy1sZWF2ZScpO1xuICAgIHRoaXMuX2RyYWdBbmltYXRpb25TdGFibGUkXG4gICAgICAucGlwZSh0YWtlKDEpLCB0YWtlVW50aWwodGhpcy5fZHJhZ2xlYXZlJCksIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSlcbiAgICAgIC5zdWJzY3JpYmUoe2NvbXBsZXRlOiAoKSA9PiB1bnNldENzc0NsYXNzKHRoaXMuX2hvc3QsICdkcmFnLWxlYXZlJyl9KTtcblxuICAgIHRoaXMudW5zZXREcmFnU3RhdGUoe3Vuc2V0RHJhZ1NvdXJjZTogZmFsc2V9KTtcblxuICAgIC8vIEFjdGl2YXRlIHRoZSB2aWV3IG5leHQgdG8gdGhlIHZpZXcgYmVpbmcgZHJhZ2dlZCBvdXQgb2YgdGhpcyB0YWJiYXIuIEJ1dCwgZG8gbm90IHB1c2ggdGhlIG5hdmlnYXRpb24gaW50byBicm93c2luZyBoaXN0b3J5IHN0YWNrLlxuICAgIGlmICh0aGlzLmRyYWdTb3VyY2VWaWV3VGFiICYmIHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIuYWN0aXZlKSB7XG4gICAgICB0aGlzLl9yb3V0ZXIubmF2aWdhdGUobGF5b3V0ID0+IGxheW91dC5hY3RpdmF0ZUFkamFjZW50Vmlldyh0aGlzLmRyYWdTb3VyY2VWaWV3VGFiIS52aWV3SWQpLCB7c2tpcExvY2F0aW9uQ2hhbmdlOiB0cnVlfSkudGhlbigpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgaW52b2tlZCB3aGlsZSB0aGUgdXNlciBpcyBkcmFnZ2luZyBhIHRhYiBvdmVyIHRoaXMgdGFiYmFyLlxuICAgKi9cbiAgcHJpdmF0ZSBvblRhYmJhckRyYWdPdmVyKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBhbGxvdyB2aWV3IGRyb3BcblxuICAgIC8vIExvY2F0ZSB0aGUgdGFiIG92ZXIgd2hpY2ggdGhlIHVzZXIgaXMgZHJhZ2dpbmcgdGhlIHRhYiwgYnV0IG9ubHkgYWZ0ZXIgcGVuZGluZyB0cmFuc2l0aW9ucyBoYXZlIGVuZGVkIHRvIHByZXZlbnQgdGFicyBmcm9tIHNsaWRpbmcgYmFjayBhbmQgZm9ydGguXG4gICAgaWYgKHRoaXMuaXNEcmFnQW5pbWF0aW9uU3RhYmxlKCkpIHtcbiAgICAgIHRoaXMuZHJvcFRhcmdldFZpZXdUYWIgPSB0aGlzLmNvbXB1dGVEcm9wVGFyZ2V0KGV2ZW50KTtcbiAgICAgIC8vIFN5bmNocm9uaXplIHRoZSB3aWR0aCBvZiB0aGUgZHJhZyBzb3VyY2UgcGxhY2Vob2xkZXIgd2l0aCB0aGUgZHJhZyBwb2ludGVyIHBvc2l0aW9uIHRvIG1vdmUgYWN0aW9ucyBhbG9uZyB3aXRoIHRoZSBwb2ludGVyLlxuICAgICAgc2V0Q3NzVmFyaWFibGUodGhpcy5faG9zdCwgeyctLcm1cGFydC1iYXItZHJhZy1pbWFnZS1wbGFjZWhvbGRlci13aWR0aCc6IGAke3RoaXMuY2FsY3VsYXRlRHJhZ0ltYWdlUGxhY2Vob2xkZXJXaWR0aChldmVudCl9cHhgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgZHJvcHMgYSB0YWIgaW4gdGhpcyB0YWJiYXIuXG4gICAqL1xuICBwcml2YXRlIG9uVGFiYmFyRHJvcCgpOiB2b2lkIHtcbiAgICB0aGlzLl92aWV3RHJhZ1NlcnZpY2UuZGlzcGF0Y2hWaWV3TW92ZUV2ZW50KHtcbiAgICAgIHNvdXJjZToge1xuICAgICAgICB3b3JrYmVuY2hJZDogdGhpcy5fZHJhZ0RhdGEhLndvcmtiZW5jaElkLFxuICAgICAgICBwYXJ0SWQ6IHRoaXMuX2RyYWdEYXRhIS5wYXJ0SWQsXG4gICAgICAgIHZpZXdJZDogdGhpcy5fZHJhZ0RhdGEhLnZpZXdJZCxcbiAgICAgICAgYWx0ZXJuYXRpdmVWaWV3SWQ6IHRoaXMuX2RyYWdEYXRhIS5hbHRlcm5hdGl2ZVZpZXdJZCxcbiAgICAgICAgdmlld1VybFNlZ21lbnRzOiB0aGlzLl9kcmFnRGF0YSEudmlld1VybFNlZ21lbnRzLFxuICAgICAgICBuYXZpZ2F0aW9uSGludDogdGhpcy5fZHJhZ0RhdGEhLm5hdmlnYXRpb25IaW50LFxuICAgICAgICBjbGFzc0xpc3Q6IHRoaXMuX2RyYWdEYXRhIS5jbGFzc0xpc3QsXG4gICAgICB9LFxuICAgICAgdGFyZ2V0OiB7XG4gICAgICAgIHdvcmtiZW5jaElkOiB0aGlzLl93b3JrYmVuY2hJZCxcbiAgICAgICAgcG9zaXRpb246IHRoaXMuZHJvcFRhcmdldFZpZXdUYWIgPT09ICdlbmQnID8gJ2VuZCcgOiB0aGlzLl92aWV3VGFicy5pbmRleE9mKHRoaXMuZHJvcFRhcmdldFZpZXdUYWIhKSxcbiAgICAgICAgZWxlbWVudElkOiB0aGlzLl9wYXJ0LmlkLFxuICAgICAgfSxcbiAgICB9KTtcblxuICAgIC8vIFdhaXQgdW5kb2luZyB0aGUgZHJhZyBzdGF0ZSB1bnRpbCBmbHVzaGVkIHRhYiBjaGFuZ2VzIHRvIHRoZSBET00sIGkuZS4sIGFmdGVyIHRoZSBsYXlvdXQgcm91dGluZyBjeWNsZSBjb21wbGV0ZXMuXG4gICAgLy8gSWYgd2Ugd2VyZSB0byB1bmRvIHRoZSBkcmFnIHN0YXRlIGltbWVkaWF0ZWx5IGR1cmluZyB0aGUgY291cnNlIG9mIHRoZSBkcm9wIGV2ZW50LCB0aGUgdGFiIGxheW91dCB3b3VsZCB0ZW1wb3JhcmlseVxuICAgIC8vIHJldmVydCB0byB0aGUgc3RhdGUgYmVmb3JlIHRoZSBkcmFnIG9wZXJhdGlvbiwgcmVzdWx0aW5nIGluIGFuIHVnbHkgZmxpY2tlci5cbiAgICBmaXJzdFZhbHVlRnJvbSh0aGlzLl93b3JrYmVuY2hMYXlvdXRTZXJ2aWNlLm9uTGF5b3V0Q2hhbmdlJCkudGhlbigoKSA9PiB7XG4gICAgICB0aGlzLnVuc2V0RHJhZ1N0YXRlKCk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogTG9jYXRlcyB0aGUgdGFiIGJlZm9yZSB3aGljaCB0aGUgZHJhZ2dlZCB0YWIgaXMgdG8gYmUgaW5zZXJ0ZWQgd2hlbiBpdCBpcyBkcm9wcGVkLiBEcmFnZ2luZyBiZXlvbmQgdGhlIGxhc3QgdGFiIHJldHVybnMgYGVuZGAuXG4gICAqL1xuICBwdWJsaWMgY29tcHV0ZURyb3BUYXJnZXQoZXZlbnQ6IERyYWdFdmVudCk6IFZpZXdUYWJDb21wb25lbnQgfCAnZW5kJyB7XG4gICAgY29uc3Qgdmlld0RyYWdJbWFnZVJlY3QgPSB0aGlzLl92aWV3VGFiRHJhZ0ltYWdlUmVuZGVyZXIuY2FsY3VsYXRlRHJhZ0ltYWdlUmVjdCh0aGlzLl9kcmFnRGF0YSEsIGV2ZW50KTtcbiAgICBjb25zdCB2aWV3VGFicyA9IHRoaXMuX3ZpZXdUYWJzLmZpbHRlcih2aWV3VGFiID0+IHZpZXdUYWIgIT09IHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIpO1xuXG4gICAgZm9yIChjb25zdCB2aWV3VGFiIG9mIHZpZXdUYWJzKSB7XG4gICAgICBjb25zdCB2aWV3VGFiUmVjdCA9IHZpZXdUYWIuaG9zdC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGNvbnN0IHZpZXdUYWJNaWRkbGUgPSB2aWV3VGFiUmVjdC5sZWZ0ICsgKHZpZXdUYWJSZWN0LndpZHRoIC8gMik7XG4gICAgICBpZiAodmlld0RyYWdJbWFnZVJlY3QubGVmdCA8IHZpZXdUYWJNaWRkbGUgJiYgKHZpZXdUYWIgIT09IHRoaXMuZHJvcFRhcmdldFZpZXdUYWIgfHwgdmlld0RyYWdJbWFnZVJlY3QucmlnaHQgPCB2aWV3VGFiTWlkZGxlKSkge1xuICAgICAgICByZXR1cm4gdmlld1RhYjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICdlbmQnO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGZ1bmN0aW9uIGZvciBzbmFwcGluZyB0aGUgZHJhZyBpbWFnZSB0byB0aGUgdGFiYmFyIHdoZW4gZHJhZ2dpbmcgbmVhciBpdC5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRHJhZ0ltYWdlQ29uc3RyYWluRm4oKTogQ29uc3RyYWluRm4ge1xuICAgIGNvbnN0IGhvc3RMZWZ0ID0gdGhpcy5faG9zdC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0O1xuICAgIGNvbnN0IG1heFZpZXdwb3J0V2lkdGggPSB0aGlzLmNhbGN1bGF0ZU1heFZpZXdwb3J0V2lkdGgoKTtcbiAgICByZXR1cm4gKHJlY3Q6IFZpZXdEcmFnSW1hZ2VSZWN0KTogVmlld0RyYWdJbWFnZVJlY3QgPT4ge1xuICAgICAgY29uc3Qgdmlld3BvcnRCb3VuZGluZ0JveCA9IHRoaXMuX3ZpZXdwb3J0RWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgcmV0dXJuIG5ldyBWaWV3RHJhZ0ltYWdlUmVjdCh7XG4gICAgICAgIHg6IE1hdGgubWluKE1hdGgubWF4KGhvc3RMZWZ0ICsgdGhpcy5fdGFiYmFySW5kZW50LmxlZnQsIHJlY3QueCksIGhvc3RMZWZ0ICsgbWF4Vmlld3BvcnRXaWR0aCAtIHJlY3Qud2lkdGggLSB0aGlzLl90YWJiYXJJbmRlbnQucmlnaHQpLFxuICAgICAgICB5OiB2aWV3cG9ydEJvdW5kaW5nQm94LnRvcCxcbiAgICAgICAgd2lkdGg6IHJlY3Qud2lkdGgsXG4gICAgICAgIGhlaWdodDogdmlld3BvcnRCb3VuZGluZ0JveC5oZWlnaHQsIC8vIGZpdCBpbnRvIHRhYmJhciwgZS5nLiwgd2hlbiBkcmFnZ2luZyBhIHRhYiBpbnRvIGEgdGFiYmFyIG9mIGEgZGlmZmVyZW50IGhlaWdodFxuICAgICAgfSk7XG4gICAgfTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDYWxjdWxhdGVzIHRoZSBtYXhpbXVtIHdpZHRoIG9mIHRoZSB0YWJiYXIgdmlld3BvcnQgYmVmb3JlIGFuIG92ZXJmbG93IHdvdWxkIG9jY3VyLCB3aGljaCBjYW4gdGhlbiBiZSB1c2VkIHRvIGNvbnN0cmFpbiB0aGUgZHJhZyBpbWFnZS5cbiAgICpcbiAgICogVG8gY2FsY3VsYXRlIHRoZSBlZmZlY3RpdmUgd2lkdGgsIHdlIG5lZWQgdG8gc2ltdWxhdGUgYW4gb3ZlcmZsb3cgaW4gdGhlIERPTS4gVGhlcmVmb3JlLCBjYWxsIHRoaXMgbWV0aG9kIG9ubHkgZnJvbSBgZHJhZ3N0YXJ0YCBhbmQgbm90XG4gICAqIGZyb20gYGRyYWdvdmVyYCBhbmQgZGlzYWJsZSBhbmltYXRpb25zLlxuICAgKi9cbiAgcHJpdmF0ZSBjYWxjdWxhdGVNYXhWaWV3cG9ydFdpZHRoKCk6IG51bWJlciB7XG4gICAgY29uc3QgY3VycmVudFdpZHRoID0gdGhpcy5faG9zdC5zdHlsZS5nZXRQcm9wZXJ0eVZhbHVlKCctLcm1cGFydC1iYXItZHJhZy1pbWFnZS1wbGFjZWhvbGRlci13aWR0aCcpO1xuXG4gICAgLy8gRGlzYWJsZSBhbmltYXRpb25zIGR1cmluZyBjYWxjdWxhdGlvbiBhbmQgZm9yY2UgdGhlIHZpZXdwb3J0IHRvIG92ZXJmbG93LlxuICAgIHNldENzc0NsYXNzKHRoaXMuX2hvc3QsICdjYWxjdWxhdGluZy1tYXgtdmlld3BvcnQtd2lkdGgnKTtcbiAgICBzZXRDc3NWYXJpYWJsZSh0aGlzLl9ob3N0LCB7Jy0tybVwYXJ0LWJhci1kcmFnLWltYWdlLXBsYWNlaG9sZGVyLXdpZHRoJzogYCR7dGhpcy5faG9zdC5jbGllbnRXaWR0aH1weGB9KTtcbiAgICB0cnkge1xuICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdwb3J0RWxlbWVudC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLndpZHRoO1xuICAgIH1cbiAgICBmaW5hbGx5IHtcbiAgICAgIHNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsIHsnLS3JtXBhcnQtYmFyLWRyYWctaW1hZ2UtcGxhY2Vob2xkZXItd2lkdGgnOiBjdXJyZW50V2lkdGggfHwgbnVsbH0pO1xuICAgICAgdW5zZXRDc3NDbGFzcyh0aGlzLl9ob3N0LCAnY2FsY3VsYXRpbmctbWF4LXZpZXdwb3J0LXdpZHRoJyk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIENhbGN1bGF0ZXMgdGhlIHdpZHRoIGZvciB0aGUgZHJhZyBpbWFnZSBwbGFjZWhvbGRlci5cbiAgICpcbiAgICogLSBXaGVuIGRyYWdnaW5nIG92ZXIgdGFicywgdGhlIHdpZHRoIGlzIGVxdWFsIHRvIHRoZSB3aWR0aCBvZiB0aGUgZHJhZyBzb3VyY2UuXG4gICAqIC0gV2hlbiBkcmFnZ2luZyB0byB0aGUgcmlnaHQgb2YgdGhlIGxhc3QgdGFiLCB0aGUgd2lkdGggb2YgdGhlIHBsYWNlaG9sZGVyIGlzIGNhbGN1bGF0ZWQgYXMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlXG4gICAqICAgbGFzdCB0YWIgYW5kIHRoZSBwb3NpdGlvbiBvZiB0aGUgZHJhZ292ZXIgZXZlbnQuIEFwcGx5aW5nIHRoaXMgd2lkdGggd2lsbCByZXNpemUgdGhlIHZpZXdwb3J0LCBtb3ZpbmcgcGFydCBhY3Rpb25zIGFsb25nXG4gICAqICAgd2l0aCB0aGUgZHJhZ292ZXIgZXZlbnQuXG4gICAqL1xuICBwcml2YXRlIGNhbGN1bGF0ZURyYWdJbWFnZVBsYWNlaG9sZGVyV2lkdGgoZXZlbnQ6IERyYWdFdmVudCk6IG51bWJlciB7XG4gICAgY29uc3Qgdmlld0RyYWdJbWFnZVJlY3QgPSB0aGlzLl92aWV3VGFiRHJhZ0ltYWdlUmVuZGVyZXIuY2FsY3VsYXRlRHJhZ0ltYWdlUmVjdCh0aGlzLl9kcmFnRGF0YSEsIGV2ZW50KTtcbiAgICBjb25zdCBsYXN0Vmlld1RhYiA9IHRoaXMuX3ZpZXdUYWJzLmZpbHRlcih2aWV3VGFiID0+IHZpZXdUYWIgIT09IHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIpLmF0KC0xKTtcbiAgICBjb25zdCBsYXN0Vmlld1RhYlJpZ2h0ID0gbGFzdFZpZXdUYWI/Lmhvc3QuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkucmlnaHQgPz8gdGhpcy5faG9zdC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKS5sZWZ0ICsgdGhpcy5fdGFiYmFySW5kZW50LmxlZnQ7XG4gICAgcmV0dXJuIE1hdGgubWF4KGxhc3RWaWV3VGFiUmlnaHQgKyB2aWV3RHJhZ0ltYWdlUmVjdC53aWR0aCwgdmlld0RyYWdJbWFnZVJlY3QucmlnaHQpIC0gbGFzdFZpZXdUYWJSaWdodDtcbiAgfVxuXG4gIC8qKlxuICAgKiBJbmRpY2F0ZXMgd2hldGhlciBDU1MgYW5pbWF0aW9ucyBoYXZlIGZpbmlzaGVkIHdoZW4gZHJhZ2dpbmcgYSB0YWIgb3ZlciB0aGUgdGFiYmFyLlxuICAgKiBUaGUgYW5pbWF0aW9uIGlzIGNvbnNpZGVyZWQgc3RhYmxlIHdoZW4gYWxsIHRhYnMgaGF2ZSBtb3ZlZCB0byB0aGVpciBmaW5hbCBwb3NpdGlvbi5cbiAgICovXG4gIHByaXZhdGUgaXNEcmFnQW5pbWF0aW9uU3RhYmxlKCk6IGJvb2xlYW4ge1xuICAgIGlmICghdGhpcy5kcm9wVGFyZ2V0Vmlld1RhYikge1xuICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdUYWJzLmV2ZXJ5KHZpZXdUYWIgPT4gZ2V0Q3NzVHJhbnNsYXRpb24odmlld1RhYi5ob3N0KS50cmFuc2xhdGVYID09PSAnbm9uZScpO1xuICAgIH1cblxuICAgIGNvbnN0IHZpZXdUYWJzID0gdGhpcy5fdmlld1RhYnMuZmlsdGVyKHZpZXdUYWIgPT4gdmlld1RhYiAhPT0gdGhpcy5kcmFnU291cmNlVmlld1RhYik7XG4gICAgY29uc3QgZHJvcFRhcmdldEluZGV4ID0gdGhpcy5kcm9wVGFyZ2V0Vmlld1RhYiA9PT0gJ2VuZCcgPyB2aWV3VGFicy5sZW5ndGggOiB2aWV3VGFicy5pbmRleE9mKHRoaXMuZHJvcFRhcmdldFZpZXdUYWIhKTtcbiAgICBjb25zdCBkcmFnU291cmNlV2lkdGggPSB0aGlzLl9kcmFnRGF0YSEudmlld1RhYldpZHRoO1xuXG4gICAgcmV0dXJuIHZpZXdUYWJzLmV2ZXJ5KCh2aWV3VGFiLCBpKSA9PiB7XG4gICAgICBjb25zdCB2aWV3VGFiVHJhbnNsYXRlWCA9IGdldENzc1RyYW5zbGF0aW9uKHZpZXdUYWIuaG9zdCkudHJhbnNsYXRlWDtcbiAgICAgIC8vIEV4cGVjdCB0YWJzIHByZWNlZGluZyB0aGUgZHJvcCB0YXJnZXQgbm90IHRvIGJlIHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0LlxuICAgICAgaWYgKGkgPCBkcm9wVGFyZ2V0SW5kZXggJiYgdmlld1RhYlRyYW5zbGF0ZVggIT09ICdub25lJykge1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICAvLyBFeHBlY3QgZHJvcCB0YXJnZXQgYW5kIHRhYnMgZm9sbG93aW5nIHRoZSBkcm9wIHRhcmdldCB0byBiZSBzaGlmdGVkIHRvIHRoZSByaWdodC5cbiAgICAgIGlmIChpID49IGRyb3BUYXJnZXRJbmRleCAmJiBNYXRoLmZsb29yKE51bWJlcih2aWV3VGFiVHJhbnNsYXRlWCkpICE9PSBNYXRoLmZsb29yKGRyYWdTb3VyY2VXaWR0aCkpIHsgLy8gY29tcGFyZSBmbG9vcmVkIG51bWJlcnMgYmVjYXVzZSBgdHJhbnNsYXRlWGAgaXMgbm90IHByZWNpc2VcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHRydWU7XG4gICAgfSk7XG4gIH1cblxuICBwcml2YXRlIHVuc2V0RHJhZ1N0YXRlKG9wdGlvbnM/OiB7dW5zZXREcmFnU291cmNlPzogYm9vbGVhbn0pOiB2b2lkIHtcbiAgICBpZiAob3B0aW9ucz8udW5zZXREcmFnU291cmNlID8/IHRydWUpIHtcbiAgICAgIHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIgPSBudWxsO1xuICAgIH1cblxuICAgIHRoaXMuZHJvcFRhcmdldFZpZXdUYWIgPSBudWxsO1xuICAgIHRoaXMuX2RyYWdEYXRhID0gbnVsbDtcbiAgICB0aGlzLl92aWV3VGFiRHJhZ0ltYWdlUmVuZGVyZXIudW5zZXRDb25zdHJhaW5EcmFnSW1hZ2VSZWN0Rm4odGhpcy5fY29uc3RyYWluRm4hKTtcbiAgICB0aGlzLl9jb25zdHJhaW5GbiA9IG51bGw7XG5cbiAgICB1bnNldENzc0NsYXNzKHRoaXMuX2hvc3QsICdkcmFnLW92ZXInKTtcbiAgICB1bnNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsICctLcm1cGFydC1iYXItZHJhZy1zb3VyY2Utd2lkdGgnLCAnLS3JtXBhcnQtYmFyLWRyYWctaW1hZ2UtcGxhY2Vob2xkZXItd2lkdGgnKTtcbiAgICB0aGlzLl92aWV3RHJhZ1NlcnZpY2UudW5zZXRUYWJiYXJEcmFnb3Zlcih0aGlzLl9wYXJ0LmlkKTtcbiAgfVxuXG4gIHByaXZhdGUgZ2V0IF92aWV3VGFicygpOiBWaWV3VGFiQ29tcG9uZW50W10ge1xuICAgIHJldHVybiB0aGlzLl92aWV3VGFicyQudmFsdWU7XG4gIH1cblxuICAvKipcbiAgICogU2Nyb2xscyB0aGUgdGFiIG9mIHRoZSBhY3RpdmUgdmlldyBpbnRvIHZpZXcuXG4gICAqL1xuICBwcml2YXRlIGluc3RhbGxBY3RpdmVWaWV3U2Nyb2xsZXIoKTogdm9pZCB7XG4gICAgdGhpcy5fdmlld1RhYnMkXG4gICAgICAucGlwZShcbiAgICAgICAgc3dpdGNoTWFwKHZpZXdUYWJzID0+IGNvbWJpbmVMYXRlc3Qodmlld1RhYnMubWFwKHZpZXdUYWIgPT4gdmlld1RhYi52aWV3LmFjdGl2ZSQpKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICAvLyBUaGVyZSBtYXkgYmUgbm8gYWN0aXZlIHZpZXcgaW4gdGhlIHRhYmJhciwgZS5nLiwgd2hlbiBkcmFnZ2luZyB0aGUgbGFzdCB2aWV3IG91dCBvZiB0aGUgdGFiYmFyLlxuICAgICAgICBjb25zdCBhY3RpdmVWaWV3VGFiID0gdGhpcy5fdmlld1RhYnMuZmluZCh2aWV3VGFiID0+IHZpZXdUYWIuYWN0aXZlKTtcbiAgICAgICAgaWYgKGFjdGl2ZVZpZXdUYWIgJiYgIXRoaXMuX3ZpZXdwb3J0Q29tcG9uZW50LmlzRWxlbWVudEluVmlldyhhY3RpdmVWaWV3VGFiLmhvc3QsICdmdWxsJykpIHtcbiAgICAgICAgICB0aGlzLl92aWV3cG9ydENvbXBvbmVudC5zY3JvbGxJbnRvVmlldyhhY3RpdmVWaWV3VGFiLmhvc3QpO1xuICAgICAgICB9XG4gICAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBVcGRhdGVzIHtAbGluayDJtVdvcmtiZW5jaFZpZXd9IHdoZW4gaXRzIHRhYiBpcyBzY3JvbGxlZCBpbnRvIHZpZXcuXG4gICAqL1xuICBwcml2YXRlIGluc3RhbGxTY3JvbGxlZEludG9WaWV3VXBkYXRlcigpOiB2b2lkIHtcbiAgICB0aGlzLl92aWV3cG9ydENoYW5nZSRcbiAgICAgIC5waXBlKFxuICAgICAgICBtYXAoKCkgPT4gdGhpcy5fdmlld1RhYnMpLFxuICAgICAgICBmaWx0ZXJBcnJheSh2aWV3VGFiID0+IHZpZXdUYWIgIT09IHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIpLCAvLyBza2lwIGRyYWcgc291cmNlIGFzIGFsd2F5cyBzY3JvbGxlZCBvdXQgb2Ygdmlld1xuICAgICAgICBtZXJnZU1hcCh2aWV3VGFicyA9PiBmcm9tKHZpZXdUYWJzKSksXG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCh0aGlzLl9kZXN0cm95UmVmKSxcbiAgICAgIClcbiAgICAgIC5zdWJzY3JpYmUodmlld1RhYiA9PiB7XG4gICAgICAgIHZpZXdUYWIudmlldy5zY3JvbGxlZEludG9WaWV3ID0gdGhpcy5fdmlld3BvcnRDb21wb25lbnQuaXNFbGVtZW50SW5WaWV3KHZpZXdUYWIuaG9zdCwgJ2Z1bGwnKTtcbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnN0YWxsVmlld0RyYWdMaXN0ZW5lcigpOiB2b2lkIHtcbiAgICB0aGlzLl92aWV3RHJhZ1NlcnZpY2Uudmlld0RyYWckKHRoaXMuX2hvc3QpXG4gICAgICAucGlwZSh0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZikpXG4gICAgICAuc3Vic2NyaWJlKChldmVudDogRHJhZ0V2ZW50KSA9PiB7XG4gICAgICAgIHN3aXRjaCAoZXZlbnQudHlwZSkge1xuICAgICAgICAgIGNhc2UgJ2RyYWdlbnRlcic6XG4gICAgICAgICAgICB0aGlzLm9uVGFiYmFyRHJhZ0VudGVyKGV2ZW50KTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIGNhc2UgJ2RyYWdvdmVyJzpcbiAgICAgICAgICAgIHRoaXMub25UYWJiYXJEcmFnT3ZlcihldmVudCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdkcmFnbGVhdmUnOlxuICAgICAgICAgICAgdGhpcy5vblRhYmJhckRyYWdMZWF2ZSgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJvcCc6XG4gICAgICAgICAgICB0aGlzLm9uVGFiYmFyRHJvcCgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgIH1cbiAgICAgIH0pO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnN0YWxsVmlld3BvcnRDbGllbnRTaXplRGV0ZWN0b3IoKTogdm9pZCB7XG4gICAgZnJvbURpbWVuc2lvbiQodGhpcy5fdmlld3BvcnRDb21wb25lbnQudmlld3BvcnRDbGllbnRFbGVtZW50KVxuICAgICAgLnBpcGUoXG4gICAgICAgIHN1YnNjcmliZUluc2lkZShmbiA9PiB0aGlzLl96b25lLnJ1bihmbikpLFxuICAgICAgICB0YWtlVW50aWxEZXN0cm95ZWQodGhpcy5fZGVzdHJveVJlZiksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKCgpID0+IHRoaXMuX3ZpZXdwb3J0Q2hhbmdlJC5uZXh0KCkpO1xuICB9XG5cbiAgcHJpdmF0ZSBpbnN0YWxsVGFiYmFySW5kZW50U2l6ZURldGVjdG9yKCk6IHZvaWQge1xuICAgIGNvbWJpbmVMYXRlc3QoW2Zyb21EaW1lbnNpb24kKHRoaXMuX3RhYkNvcm5lclJhZGl1c0VsZW1lbnQubmF0aXZlRWxlbWVudCksIGZyb21EaW1lbnNpb24kKHRoaXMuX3BhZGRpbmdJbmxpbmVFbGVtZW50Lm5hdGl2ZUVsZW1lbnQpXSlcbiAgICAgIC5waXBlKFxuICAgICAgICBzdWJzY3JpYmVJbnNpZGUoZm4gPT4gdGhpcy5fem9uZS5ydW5PdXRzaWRlQW5ndWxhcihmbikpLFxuICAgICAgICBtYXBBcnJheShkaW1lbnNpb24gPT4gZGltZW5zaW9uLmNsaWVudFdpZHRoKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKHRoaXMuX2Rlc3Ryb3lSZWYpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoW3RhYkNvcm5lclJhZGl1cywgcGFkZGluZ0lubGluZV0pID0+IHtcbiAgICAgICAgdGhpcy5fdGFiYmFySW5kZW50ID0ge2xlZnQ6IHRhYkNvcm5lclJhZGl1cyArIHBhZGRpbmdJbmxpbmUsIHJpZ2h0OiB0YWJDb3JuZXJSYWRpdXMgKyBwYWRkaW5nSW5saW5lfTtcbiAgICAgICAgc2V0Q3NzVmFyaWFibGUodGhpcy5faG9zdCwgeyctLcm1cGFydC1iYXItaW5kZW50LWxlZnQnOiBgJHt0aGlzLl90YWJiYXJJbmRlbnQubGVmdH1weGB9KTtcbiAgICAgICAgc2V0Q3NzVmFyaWFibGUodGhpcy5faG9zdCwgeyctLcm1cGFydC1iYXItaW5kZW50LXJpZ2h0JzogYCR7dGhpcy5fdGFiYmFySW5kZW50LnJpZ2h0fXB4YH0pO1xuICAgICAgfSk7XG4gIH1cbn1cbiIsIjxzY2ktdmlld3BvcnQgY2xhc3M9XCJ0YWJiYXJcIiBzY3JvbGxiYXJTdHlsZT1cImhpZGRlblwiXG4gICAgICAgICAgICAgIFtjbGFzcy5kcmFnb3Zlcl09XCJkcmFnb3ZlciQgfCBhc3luY1wiXG4gICAgICAgICAgICAgIHNjaURpbWVuc2lvbiAoc2NpRGltZW5zaW9uQ2hhbmdlKT1cIm9uVGFiYmFyVmlld3BvcnREaW1lbnNpb25DaGFuZ2UoKVwiXG4gICAgICAgICAgICAgIChzY3JvbGwpPVwib25TY3JvbGwoKVwiPlxuICA8bmctY29udGFpbmVyICpuZ0Zvcj1cImxldCB2aWV3SWQgb2Ygdmlld0lkcyQgfCBhc3luYztcIj5cbiAgICA8ZGl2IGNsYXNzPVwiZGl2aWRlclwiICpuZ0lmPVwidmlld3RhYiA9PT0gZHJvcFRhcmdldFZpZXdUYWJcIj48L2Rpdj5cbiAgICA8d2Itdmlldy10YWIgI3ZpZXd0YWJcbiAgICAgICAgICAgICAgICAgW3ZpZXdJZF09XCJ2aWV3SWRcIlxuICAgICAgICAgICAgICAgICBbY2xhc3MuZHJhZy1zb3VyY2VdPVwidmlld3RhYiA9PT0gZHJhZ1NvdXJjZVZpZXdUYWJcIlxuICAgICAgICAgICAgICAgICBbY2xhc3MuZHJvcC10YXJnZXRdPVwidmlld3RhYiA9PT0gZHJvcFRhcmdldFZpZXdUYWJcIj5cbiAgICA8L3diLXZpZXctdGFiPlxuICAgIDxkaXYgY2xhc3M9XCJkaXZpZGVyXCI+PC9kaXY+XG4gIDwvbmctY29udGFpbmVyPlxuXG4gIDwhLS0gUGxhY2Vob2xkZXIgZWxlbWVudCB0byBncm93IHRoZSB2aWV3cG9ydCB0byBmaXQgdGhlIGRyYWcgaW1hZ2UuIC0tPlxuICA8ZGl2IGNsYXNzPVwiZHJhZy1pbWFnZS1wbGFjZWhvbGRlclwiPjwvZGl2PlxuPC9zY2ktdmlld3BvcnQ+XG48d2ItcGFydC1hY3Rpb24tYmFyLz5cbjx3Yi12aWV3LWxpc3QtYnV0dG9uLz5cblxuPCEtLSBFbGVtZW50IGZvciBpbmplY3RpbmcgdGhlIGNvcm5lciByYWRpdXMgaW50byB0aGUgY29tcG9uZW50LiAtLT5cbjxkaXYgY2xhc3M9XCJ0YWItY29ybmVyLXJhZGl1c1wiICN0YWJfY29ybmVyX3JhZGl1cz48L2Rpdj5cbjwhLS0gRWxlbWVudCBmb3IgaW5qZWN0aW5nIHRoZSB0YWJiYXIgcGFkZGluZyBpbnRvIHRoZSBjb21wb25lbnQuIC0tPlxuPGRpdiBjbGFzcz1cInBhZGRpbmctaW5saW5lXCIgI3BhZGRpbmdfaW5saW5lPjwvZGl2PlxuIl19
528
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoicGFydC1iYXIuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2Npb24vd29ya2JlbmNoL3NyYy9saWIvcGFydC9wYXJ0LWJhci9wYXJ0LWJhci5jb21wb25lbnQudHMiLCIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9zY2lvbi93b3JrYmVuY2gvc3JjL2xpYi9wYXJ0L3BhcnQtYmFyL3BhcnQtYmFyLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBOzs7Ozs7OztHQVFHO0FBRUgsT0FBTyxFQUFDLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLFVBQVUsRUFBRSxZQUFZLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBcUIsTUFBTSxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsWUFBWSxFQUFDLE1BQU0sZUFBZSxDQUFDO0FBQ25LLE9BQU8sRUFBQyxnQkFBZ0IsRUFBQyxNQUFNLGdDQUFnQyxDQUFDO0FBQ2hFLE9BQU8sRUFBQyxHQUFHLEVBQUUsUUFBUSxFQUFFLFNBQVMsRUFBQyxNQUFNLGdCQUFnQixDQUFDO0FBQ3hELE9BQU8sRUFBQyxJQUFJLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxVQUFVLEVBQW9CLE9BQU8sRUFBRSxLQUFLLEVBQUMsTUFBTSxNQUFNLENBQUM7QUFDMUYsT0FBTyxFQUFjLHdCQUF3QixFQUFDLE1BQU0scURBQXFELENBQUM7QUFDMUcsT0FBTyxFQUFlLGVBQWUsRUFBZ0IsTUFBTSxrQ0FBa0MsQ0FBQztBQUM5RixPQUFPLEVBQUMsaUJBQWlCLEVBQUUsV0FBVyxFQUFFLGNBQWMsRUFBRSxhQUFhLEVBQUUsZ0JBQWdCLEVBQUMsTUFBTSx1QkFBdUIsQ0FBQztBQUN0SCxPQUFPLEVBQUMsY0FBYyxFQUFDLE1BQU0sMEJBQTBCLENBQUM7QUFDeEQsT0FBTyxFQUFDLFdBQVcsRUFBRSxXQUFXLEVBQUMsTUFBTSww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QkFEdEIsWUFBWTt1QkFBQyxVQUFVLEVBQUUsQ0FBQyxRQUFRLENBQUMiLCJzb3VyY2VzQ29udGVudCI6WyIvKlxuICogQ29weXJpZ2h0IChjKSAyMDE4LTIwMjQgU3dpc3MgRmVkZXJhbCBSYWlsd2F5c1xuICpcbiAqIFRoaXMgcHJvZ3JhbSBhbmQgdGhlIGFjY29tcGFueWluZyBtYXRlcmlhbHMgYXJlIG1hZGVcbiAqIGF2YWlsYWJsZSB1bmRlciB0aGUgdGVybXMgb2YgdGhlIEVjbGlwc2UgUHVibGljIExpY2Vuc2UgMi4wXG4gKiB3aGljaCBpcyBhdmFpbGFibGUgYXQgaHR0cHM6Ly93d3cuZWNsaXBzZS5vcmcvbGVnYWwvZXBsLTIuMC9cbiAqXG4gKiBTUERYLUxpY2Vuc2UtSWRlbnRpZmllcjogRVBMLTIuMFxuICovXG5cbmltcG9ydCB7Q29tcG9uZW50LCBjb21wdXRlZCwgZWZmZWN0LCBFbGVtZW50UmVmLCBIb3N0TGlzdGVuZXIsIGluamVjdCwgTmdab25lLCBPbkRlc3Ryb3ksIFNpZ25hbCwgc2lnbmFsLCB1bnRyYWNrZWQsIHZpZXdDaGlsZCwgdmlld0NoaWxkcmVufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7Vmlld1RhYkNvbXBvbmVudH0gZnJvbSAnLi4vdmlldy10YWIvdmlldy10YWIuY29tcG9uZW50JztcbmltcG9ydCB7bWFwLCBtZXJnZU1hcCwgdGFrZVVudGlsfSBmcm9tICdyeGpzL29wZXJhdG9ycyc7XG5pbXBvcnQge2Zyb20sIGZyb21FdmVudCwgbWVyZ2UsIE9ic2VydmFibGUsIE9wZXJhdG9yRnVuY3Rpb24sIFN1YmplY3QsIHRpbWVyfSBmcm9tICdyeGpzJztcbmltcG9ydCB7Q29uc3RyYWluRm4sIFZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlcn0gZnJvbSAnLi4vLi4vdmlldy1kbmQvdmlldy10YWItZHJhZy1pbWFnZS1yZW5kZXJlci5zZXJ2aWNlJztcbmltcG9ydCB7Vmlld0RyYWdEYXRhLCBWaWV3RHJhZ1NlcnZpY2UsIFZpZXdNb3ZlRXZlbnR9IGZyb20gJy4uLy4uL3ZpZXctZG5kL3ZpZXctZHJhZy5zZXJ2aWNlJztcbmltcG9ydCB7Z2V0Q3NzVHJhbnNsYXRpb24sIHNldENzc0NsYXNzLCBzZXRDc3NWYXJpYWJsZSwgdW5zZXRDc3NDbGFzcywgdW5zZXRDc3NWYXJpYWJsZX0gZnJvbSAnLi4vLi4vY29tbW9uL2RvbS51dGlsJztcbmltcG9ydCB7ybVXb3JrYmVuY2hQYXJ0fSBmcm9tICcuLi/JtXdvcmtiZW5jaC1wYXJ0Lm1vZGVsJztcbmltcG9ydCB7ZmlsdGVyQXJyYXksIHN1YnNjcmliZUlufSBmcm9tICdAc2Npb24vdG9vbGtpdC9vcGVyYXRvcnMnO1xuaW1wb3J0IHtTY2lWaWV3cG9ydENvbXBvbmVudH0gZnJvbSAnQHNjaW9uL2NvbXBvbmVudHMvdmlld3BvcnQnO1xuaW1wb3J0IHvJtVdvcmtiZW5jaFJvdXRlcn0gZnJvbSAnLi4vLi4vcm91dGluZy/JtXdvcmtiZW5jaC1yb3V0ZXIuc2VydmljZSc7XG5pbXBvcnQge2JvdW5kaW5nQ2xpZW50UmVjdCwgZGltZW5zaW9ufSBmcm9tICdAc2Npb24vY29tcG9uZW50cy9kaW1lbnNpb24nO1xuaW1wb3J0IHtQYXJ0QWN0aW9uQmFyQ29tcG9uZW50fSBmcm9tICcuLi9wYXJ0LWFjdGlvbi1iYXIvcGFydC1hY3Rpb24tYmFyLmNvbXBvbmVudCc7XG5pbXBvcnQge1ZpZXdMaXN0QnV0dG9uQ29tcG9uZW50fSBmcm9tICcuLi92aWV3LWxpc3QtYnV0dG9uL3ZpZXctbGlzdC1idXR0b24uY29tcG9uZW50JztcbmltcG9ydCB7dGFrZVVudGlsRGVzdHJveWVkfSBmcm9tICdAYW5ndWxhci9jb3JlL3J4anMtaW50ZXJvcCc7XG5pbXBvcnQge1dPUktCRU5DSF9JRH0gZnJvbSAnLi4vLi4vd29ya2JlbmNoLWlkJztcbmltcG9ydCB7Y2xhbXB9IGZyb20gJy4uLy4uL2NvbW1vbi9tYXRoLnV0aWwnO1xuXG4vKipcbiAqIFJlbmRlcnMgdmlldyB0YWJzIGFuZCBhY3Rpb25zIG9mIGEge0BsaW5rIFdvcmtiZW5jaFBhcnR9LlxuICpcbiAqIFRhYnMgYXJlIGFkZGVkIHRvIGEgdmlld3BvcnQsIHdoaWNoIHRoZSB1c2VyIGNhbiBzY3JvbGwgaWYgbm90IGVub3VnaCBzcGFjZS4gVGhlIHZpZXdwb3J0IGdyb3dzIHdpdGggaXRzIHRhYnMsXG4gKiBhbGxvd2luZyBhY3Rpb25zIHRvIGJlIHBsYWNlZCBkaXJlY3RseSBhZnRlciB0aGUgbGFzdCB0YWIgb3Igb24gdGhlIHJpZ2h0IHNpZGUuXG4gKlxuICogIyMgRHJhZyBhbmQgRHJvcFxuICogVGhpcyBjb21wb25lbnQgc3Vic2NyaWJlcyB0byBkcmFnIGV2ZW50cyB0byB2aXN1YWxpemUgdGFicyBkdXJpbmcgYSBkcmFnIG9wZXJhdGlvbi4gVGhlIGRyYWcgb3BlcmF0aW9uIGlzIGluaXRpYXRlZCBpbiB7QGxpbmsgVmlld1RhYkNvbXBvbmVudH0uXG4gKlxuICogV2UgdXNlIG5hdGl2ZSBkcmFnIGFuZCBkcm9wIHRvIHN1cHBvcnQgZHJhZ2dpbmcgdmlld3MgdG8gb3RoZXIgd2luZG93cy5cbiAqXG4gKiBGb2xsb3dpbmcgZXZlbnRzIGFyZSB0cmlnZ2VyZWQ6XG4gKiAtIGRyYWdzdGFydDogd2hlbiBzdGFydCBkcmFnZ2luZyBhIHRhYiAob25seSByZWNlaXZlZCBpbiB0aGUgdGFiYmFyIHdoZXJlIHRoZSBkcmFnIG9wZXJhdGlvbiBoYXMgc3RhcnRlZClcbiAqIC0gZHJhZ2VuZDogICB3aGVuIGVuZCBkcmFnZ2luZyBhIHRhYiwgZWl0aGVyIHZpYSBkcm9wIG9yIGNhbmNlbCAob25seSByZWNlaXZlZCBpbiB0aGUgdGFiYmFyIHdoZXJlIHRoZSBkcmFnIG9wZXJhdGlvbiBoYXMgc3RhcnRlZClcbiAqIC0gZHJhZ2VudGVyOiB3aGVuIGEgdGFiIGVudGVycyB0aGUgdGFiYmFyXG4gKiAtIGRyYWdvdmVyOiAgd2hlbiBkcmFnZ2luZyBhIHRhYiBvdmVyIHRoZSB0YWJiYXIsIGV2ZXJ5IGZldyBodW5kcmVkIG1pbGxpc2Vjb25kc1xuICogLSBkcmFnbGVhdmU6IHdoZW4gYSB0YWIgbGVhdmVzIHRoZSB0YWJiYXJcbiAqIC0gZHJvcDogICAgICB3aGVuIHRoZSB1c2VyIGRyb3BzIGEgdGFiIGluIHRoZSB0YWJiYXJcbiAqXG4gKiAtIE5vdGUgdGhhdCBgZHJhZ2xlYXZlYCBldmVudCBpcyBub3QgZmlyZWQgb24gZHJvcCBhY3Rpb24uIFRoZXJlZm9yZSwgYWx3YXlzIGhhbmRsZSBib3RoIGV2ZW50cywgYGRyYWdsZWF2ZWAgYW5kIGBkcm9wYCBldmVudHMsIHJlc3BlY3RpdmVseS5cbiAqXG4gKiAjIyBUZXJtaW5vbG9neVxuICogLSBEcmFnIHNvdXJjZTogVGFiIHRoYXQgaXMgYmVpbmcgZHJhZ2dlZC5cbiAqIC0gRHJvcCB0YXJnZXQ6IFRhYiBiZWZvcmUgd2hpY2ggdG8gaW5zZXJ0IHRoZSBkcmFnIHNvdXJjZSBvbiBkcm9wLCBvciBgZW5kYCBpZiBkcm9wcGluZyBpdCBhZnRlciB0aGUgbGFzdCB0YWIuXG4gKiAtIERyYWcgaW1hZ2U6ICBJbWFnZSBmb3IgdGhlIHRhYiB0byBiZSBkcmFnZ2VkLiBXZSBkbyBub3QgdXNlIHRoZSBuYXRpdmUgZHJhZyBpbWFnZSBzdXBwb3J0IHRvIGNvbnRyb2wgZHJhZyBpbWFnZSBwb3NpdGlvbiBhbmQgc2l6ZSxcbiAqICAgICAgICAgICAgICAgIGUuZy4sIHRvIHNuYXAgdGhlIGRyYWcgaW1hZ2UgdG8gdGhlIHRhYmJhciB3aGVuIGRyYWdnaW5nIG5lYXIgaXQuXG4gKi9cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ3diLXBhcnQtYmFyJyxcbiAgdGVtcGxhdGVVcmw6ICcuL3BhcnQtYmFyLmNvbXBvbmVudC5odG1sJyxcbiAgc3R5bGVVcmxzOiBbJy4vcGFydC1iYXIuY29tcG9uZW50LnNjc3MnXSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIFNjaVZpZXdwb3J0Q29tcG9uZW50LFxuICAgIFZpZXdUYWJDb21wb25lbnQsXG4gICAgUGFydEFjdGlvbkJhckNvbXBvbmVudCxcbiAgICBWaWV3TGlzdEJ1dHRvbkNvbXBvbmVudCxcbiAgXSxcbn0pXG5leHBvcnQgY2xhc3MgUGFydEJhckNvbXBvbmVudCBpbXBsZW1lbnRzIE9uRGVzdHJveSB7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfaG9zdCA9IGluamVjdChFbGVtZW50UmVmPEhUTUxFbGVtZW50PikubmF0aXZlRWxlbWVudDtcbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld3BvcnRDaGFuZ2UkID0gbmV3IFN1YmplY3Q8dm9pZD4oKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfd29ya2JlbmNoSWQgPSBpbmplY3QoV09SS0JFTkNIX0lEKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfcm91dGVyID0gaW5qZWN0KMm1V29ya2JlbmNoUm91dGVyKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld1RhYkRyYWdJbWFnZVJlbmRlcmVyID0gaW5qZWN0KFZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlcik7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3ZpZXdEcmFnU2VydmljZSA9IGluamVjdChWaWV3RHJhZ1NlcnZpY2UpO1xuICBwcml2YXRlIHJlYWRvbmx5IF96b25lID0gaW5qZWN0KE5nWm9uZSk7XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld1RhYnMgPSB2aWV3Q2hpbGRyZW4oVmlld1RhYkNvbXBvbmVudCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2hvc3RCb3VuZGluZ0NsaWVudFJlY3QgPSBib3VuZGluZ0NsaWVudFJlY3QoaW5qZWN0KEVsZW1lbnRSZWYpKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfdmlld3BvcnRDb21wb25lbnQgPSB2aWV3Q2hpbGQucmVxdWlyZWQoU2NpVmlld3BvcnRDb21wb25lbnQpO1xuICBwcml2YXRlIHJlYWRvbmx5IF92aWV3cG9ydENvbXBvbmVudEVsZW1lbnQgPSB2aWV3Q2hpbGQucmVxdWlyZWQoU2NpVmlld3BvcnRDb21wb25lbnQsIHtyZWFkOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50Pn0pO1xuICBwcml2YXRlIHJlYWRvbmx5IF90YWJDb3JuZXJSYWRpdXNFbGVtZW50ID0gdmlld0NoaWxkLnJlcXVpcmVkKCd0YWJfY29ybmVyX3JhZGl1cycsIHtyZWFkOiBFbGVtZW50UmVmPEhUTUxFbGVtZW50Pn0pO1xuICBwcml2YXRlIHJlYWRvbmx5IF9wYWRkaW5nSW5saW5lRWxlbWVudCA9IHZpZXdDaGlsZC5yZXF1aXJlZCgncGFkZGluZ19pbmxpbmUnLCB7cmVhZDogRWxlbWVudFJlZjxIVE1MRWxlbWVudD59KTtcbiAgcHJpdmF0ZSByZWFkb25seSBfZmlsbGVyRWxlbWVudCA9IHZpZXdDaGlsZC5yZXF1aXJlZDxFbGVtZW50UmVmPEhUTUxFbGVtZW50Pj4oJ2ZpbGxlcicpO1xuICBwcml2YXRlIHJlYWRvbmx5IF92aWV3cG9ydEJvdW5kaW5nQm94ID0gYm91bmRpbmdDbGllbnRSZWN0KHRoaXMuX3ZpZXdwb3J0Q29tcG9uZW50RWxlbWVudCk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX21heFZpZXdwb3J0V2lkdGg6IFNpZ25hbDxudW1iZXI+O1xuXG4gIHByb3RlY3RlZCByZWFkb25seSBwYXJ0ID0gaW5qZWN0KMm1V29ya2JlbmNoUGFydCk7XG4gIHByb3RlY3RlZCByZWFkb25seSBzdGFydEFjdGlvbnMgPSBjb21wdXRlZCgoKSA9PiB0aGlzLnBhcnQuYWN0aW9ucygpLmZpbHRlcihhY3Rpb24gPT4gYWN0aW9uLmFsaWduICE9PSAnZW5kJykpO1xuICBwcm90ZWN0ZWQgcmVhZG9ubHkgZW5kQWN0aW9ucyA9IGNvbXB1dGVkKCgpID0+IHRoaXMucGFydC5hY3Rpb25zKCkuZmlsdGVyKGFjdGlvbiA9PiBhY3Rpb24uYWxpZ24gPT09ICdlbmQnKSk7XG5cbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgdGFiIGJlZm9yZSB3aGljaCB0byBpbnNlcnQgdGhlIGRyYWcgc291cmNlIG9uIGRyb3AsIG9yIGBlbmRgIGlmIGRyb3BwaW5nIGl0IGFmdGVyIHRoZSBsYXN0IHRhYi5cbiAgICovXG4gIHByb3RlY3RlZCBkcm9wVGFyZ2V0Vmlld1RhYiA9IHNpZ25hbDxWaWV3VGFiQ29tcG9uZW50IHwgJ2VuZCcgfCBudWxsPihudWxsKTtcblxuICAvKipcbiAgICogUmVmZXJlbmNlIHRvIHRoZSB0YWIgd2hlcmUgdGhlIGRyYWcgb3BlcmF0aW9uIHdhcyBzdGFydGVkLlxuICAgKiBUaGlzIHJlZmVyZW5jZSBpcyBvbmx5IHNldCBpZiB0aGUgZHJhZyBvcGVyYXRpb24gc3RhcnRlZCBvbiBhIHRhYiBvZiB0aGlzIHRhYmJhci5cbiAgICovXG4gIHByb3RlY3RlZCBkcmFnU291cmNlVmlld1RhYiA9IHNpZ25hbDxWaWV3VGFiQ29tcG9uZW50IHwgbnVsbD4obnVsbCk7XG5cbiAgLyoqXG4gICAqIFRyYW5zZmVyIGRhdGEgb2YgdGhlIHRhYiBiZWluZyBkcmFnZ2VkIG92ZXIgdGhpcyB0YWJiYXIuXG4gICAqL1xuICBwcml2YXRlIF9kcmFnRGF0YTogVmlld0RyYWdEYXRhIHwgbnVsbCA9IG51bGw7XG5cbiAgLyoqXG4gICAqIEZ1bmN0aW9uIGZvciBzbmFwcGluZyB0aGUgZHJhZyBpbWFnZSB0byB0aGUgdGFiYmFyIHdoZW4gZHJhZ2dpbmcgbmVhciBpdC5cbiAgICovXG4gIHByaXZhdGUgX2NvbnN0cmFpbkZuOiBDb25zdHJhaW5GbiB8IG51bGwgPSBudWxsO1xuXG4gIC8qKlxuICAgKiBTaWduYWxzIHdoZW4gdW5zZXR0aW5nIGRyYWcgc3RhdGUuXG4gICAqL1xuICBwcml2YXRlIF9vblVuc2V0RHJhZ1N0YXRlID0gc2lnbmFsPHZvaWQ+KHVuZGVmaW5lZCwge2VxdWFsOiAoKSA9PiBmYWxzZX0pO1xuXG4gIC8qKlxuICAgKiBUYWJiYXIgaW5kZW50cyB3aGVyZSB0byBkaXNwbGF5IHRoZSByb3VuZGVkIGJvdHRvbSBjb3JuZXJzIG9mIHRoZSBmaXJzdCBhbmQgbGFzdCB2aWV3IHRhYi5cbiAgICovXG4gIHByaXZhdGUgX3RhYmJhckluZGVudCA9IHtcbiAgICBsZWZ0OiAwLFxuICAgIHJpZ2h0OiAwLFxuICB9O1xuXG4gIGNvbnN0cnVjdG9yKCkge1xuICAgIHRoaXMuX21heFZpZXdwb3J0V2lkdGggPSB0aGlzLmNhbGN1bGF0ZU1heFZpZXdwb3J0V2lkdGgoKTtcbiAgICB0aGlzLmluc3RhbGxBY3RpdmVWaWV3U2Nyb2xsZXIoKTtcbiAgICB0aGlzLmluc3RhbGxTY3JvbGxlZEludG9WaWV3VXBkYXRlcigpO1xuICAgIHRoaXMuaW5zdGFsbFZpZXdEcmFnTGlzdGVuZXIoKTtcbiAgICB0aGlzLmluc3RhbGxUYWJiYXJJbmRlbnRTaXplVHJhY2tlcigpO1xuICAgIHRoaXMuaW5zdGFsbFZpZXdwb3J0Q2hhbmdlVHJhY2tlcigpO1xuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignZGJsY2xpY2snLCBbJyRldmVudCddKVxuICBwcm90ZWN0ZWQgb25Eb3VibGVDbGljayhldmVudDogTW91c2VFdmVudCk6IHZvaWQge1xuICAgIGlmICh0aGlzLnBhcnQuaXNJbk1haW5BcmVhKSB7XG4gICAgICB0aGlzLl9yb3V0ZXIubmF2aWdhdGUobGF5b3V0ID0+IGxheW91dC50b2dnbGVNYXhpbWl6ZWQoKSkudGhlbigpO1xuICAgIH1cbiAgICBldmVudC5zdG9wUHJvcGFnYXRpb24oKTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgaW52b2tlZCB3aGVuIHRoZSB1c2VyIHN0YXJ0cyBkcmFnZ2luZyBhIHRhYiBvZiB0aGlzIHRhYmJhciwgb25seSBpbiB0aGUgdGFiYmFyIHdoZXJlIHRoZSBkcmFnIHN0YXJ0ZWQuXG4gICAqL1xuICBwcml2YXRlIG9uVGFiRHJhZ1N0YXJ0KCk6IHZvaWQge1xuICAgIC8vIE1lbW9pemUgZHJhZyBkYXRhLlxuICAgIHRoaXMuX2RyYWdEYXRhID0gdGhpcy5fdmlld0RyYWdTZXJ2aWNlLnZpZXdEcmFnRGF0YSgpITtcblxuICAgIC8vIEluZGljYXRlIGRyYWdnaW5nIG92ZXIgdGhpcyB0YWJiYXIuXG4gICAgdGhpcy5fdmlld0RyYWdTZXJ2aWNlLnNpZ25hbFRhYmJhckRyYWdFbnRlcih0aGlzLnBhcnQuaWQpO1xuXG4gICAgLy8gU25hcCBkcmFnIGltYWdlIHRvIHRhYmJhciB3aGVuIGRyYWdnaW5nIG5lYXIgaXQuXG4gICAgdGhpcy5fY29uc3RyYWluRm4gPSB0aGlzLmNyZWF0ZURyYWdJbWFnZUNvbnN0cmFpbkZuKCk7XG4gICAgdGhpcy5fdmlld1RhYkRyYWdJbWFnZVJlbmRlcmVyLnNldENvbnN0cmFpbkRyYWdJbWFnZVJlY3RGbih0aGlzLl9jb25zdHJhaW5Gbik7XG5cbiAgICAvLyBEaXNhYmxlIHBvaW50ZXIgZXZlbnRzIHRvIG5vdCBicmVhayB0aGUgZHJhZyBvcGVyYXRpb24gKGluIEZpcmVmb3gsIGJ1dCBub3QgQ2hyb21lIGFuZCBFZGdlKS5cbiAgICByZXF1ZXN0QW5pbWF0aW9uRnJhbWUoKCkgPT4gc2V0Q3NzQ2xhc3ModGhpcy5faG9zdCwgJ3BvaW50ZXItZXZlbnRzLWRpc2FibGVkJykpO1xuXG4gICAgLy8gU2V0IENTUyBjbGFzcyB0byBub3QgYW5pbWF0ZSBzdGFydCBkcmFnZ2luZy5cbiAgICBzZXRDc3NDbGFzcyh0aGlzLl9ob3N0LCAnb24tZHJhZy1zdGFydCcpO1xuICAgIHRoaXMub25EcmFnQW5pbWF0aW9uU3RhYmxlKCgpID0+IHVuc2V0Q3NzQ2xhc3ModGhpcy5faG9zdCwgJ29uLWRyYWctc3RhcnQnKSk7XG5cbiAgICAvLyBDaGVjayBpZiB0aGUgdXNlciBjb250aW51ZXMgZHJhZ2dpbmcgb3ZlciB0aGlzIHRhYmJhci5cbiAgICAvLyBJZiBub3QsIHRoZSB1c2VyIGhhcyBxdWlja2x5IGRyYWdnZWQgdGhlIHRhYiBvdXQgb2YgdGhlIHRhYmJhciwgc28gbWFudWFsbHkgY2FsbCBgb25UYWJiYXJEcmFnRW50ZXJgIGFuZCBgb25UYWJiYXJEcmFnTGVhdmVgLlxuICAgIGZyb21FdmVudDxEcmFnRXZlbnQ+KHdpbmRvdywgJ2RyYWdlbnRlcicsIHtvbmNlOiB0cnVlfSlcbiAgICAgIC5waXBlKHRha2VVbnRpbChtZXJnZShmcm9tRXZlbnQodGhpcy5faG9zdCwgJ2RyYWdlbnRlcicpLCBmcm9tRXZlbnQodGhpcy5faG9zdCwgJ2RyYWdlbmQnKSkpKVxuICAgICAgLnN1YnNjcmliZShldmVudCA9PiB7XG4gICAgICAgIHRoaXMub25UYWJiYXJEcmFnRW50ZXIoZXZlbnQpO1xuICAgICAgICB0aGlzLm9uVGFiYmFyRHJhZ0xlYXZlKGV2ZW50KTtcbiAgICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgZW5kcyBkcmFnZ2luZyBhIHRhYiBvZiB0aGlzIHRhYmJhciwgZWl0aGVyIGJ5IGRyb3Agb3IgY2FuY2VsLCBvbmx5IGluIHRoZSB0YWJiYXIgd2hlcmUgdGhlIGRyYWcgc3RhcnRlZC5cbiAgICovXG4gIHByaXZhdGUgb25UYWJEcmFnRW5kKGV2ZW50OiBEcmFnRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBVbnNldCBkcmFnIHN0YXRlIG9ubHkgb24gY2FuY2VsLCBub3Qgb24gZHJvcCwgdG8gcHJldmVudCB0YWJzIGZyb20gdGVtcG9yYXJpbHkgcmV2ZXJ0aW5nIHRvIHRoZWlyIHByZS1kcmFnIHN0YXRlLiBEcmFnIHN0YXRlIGlzIHJlc2V0IGluIGBvblRhYk1vdmVkYCBhZnRlciBhIGRyb3AuXG4gICAgaWYgKGV2ZW50LmRhdGFUcmFuc2ZlciEuZHJvcEVmZmVjdCA9PT0gJ25vbmUnKSB7XG4gICAgICAvLyBSZWFjdGl2YXRlIHRoZSBkcmFnIHNvdXJjZSB2aWV3IG9uIGNhbmNlbC5cbiAgICAgIHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIoKT8udmlldygpLmFjdGl2YXRlKHtza2lwTG9jYXRpb25DaGFuZ2U6IHRydWV9KS50aGVuKCk7XG4gICAgICAvLyBVbnNldCBkcmFnIHN0YXRlLlxuICAgICAgdGhpcy51bnNldERyYWdTdGF0ZSgpO1xuICAgIH1cbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgaW52b2tlZCB3aGVuIHRoZSBsYXlvdXQgaGFzIGNoYW5nZWQgYWZ0ZXIgYSBkcm9wLiBUaGUgZHJvcCBtYXkgbm90IGJlIHJlbGF0ZWQgdG8gYSB0YWIgb2YgdGhpcyB0YWJiYXIuXG4gICAqL1xuICBwcml2YXRlIG9uVGFiTW92ZWQoZXZlbnQ6IFZpZXdNb3ZlRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBVbnNldCBkcmFnIHN0YXRlIG9ubHkgaWYgbm8gbmV3IGRyYWcgaGFzIHN0YXJ0ZWQgc2luY2UgdGhlIGRyb3AuXG4gICAgaWYgKHRoaXMuX2RyYWdEYXRhPy51aWQgPT09IGV2ZW50LmRyYWdEYXRhPy51aWQpIHtcbiAgICAgIHRoaXMudW5zZXREcmFnU3RhdGUoKTtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogTWV0aG9kIGludm9rZWQgd2hlbiB0aGUgdXNlciBkcmFncyBhIHRhYiBpbnRvIHRoaXMgdGFiYmFyLlxuICAgKi9cbiAgcHJpdmF0ZSBvblRhYmJhckRyYWdFbnRlcihldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XG4gICAgLy8gTWVtb2l6ZSBkcmFnIGRhdGEuXG4gICAgY29uc3QgZHJhZ0RhdGEgPSB0aGlzLl9kcmFnRGF0YSA9IHRoaXMuX3ZpZXdEcmFnU2VydmljZS52aWV3RHJhZ0RhdGEoKSE7XG5cbiAgICAvLyBJbmRpY2F0ZSBkcmFnZ2luZyBvdmVyIHRoaXMgdGFiYmFyLlxuICAgIHRoaXMuX3ZpZXdEcmFnU2VydmljZS5zaWduYWxUYWJiYXJEcmFnRW50ZXIodGhpcy5wYXJ0LmlkKTtcblxuICAgIC8vIFNuYXAgZHJhZyBpbWFnZSB0byB0YWJiYXIgd2hlbiBkcmFnZ2luZyBuZWFyIGl0LlxuICAgIHRoaXMuX2NvbnN0cmFpbkZuID0gdGhpcy5jcmVhdGVEcmFnSW1hZ2VDb25zdHJhaW5GbigpO1xuICAgIHRoaXMuX3ZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlci5zZXRDb25zdHJhaW5EcmFnSW1hZ2VSZWN0Rm4odGhpcy5fY29uc3RyYWluRm4pO1xuXG4gICAgLy8gU2V0IGRyYWcgc291cmNlLCBidXQgb25seSBpZiBzdGFydGVkIHRoZSBkcmFnIG9wZXJhdGlvbiBpbiB0aGlzIHBhcnQuXG4gICAgLy8gV2UgZG8gbm90IHNldCB0aGUgZHJhZyBzb3VyY2UgaW4gYGRyYWdzdGFydGAgdG8gbm90IGJyZWFrIHRoZSBkcmFnIG9wZXJhdGlvbiAoaW4gQ2hyb21lIGFuZCBFZGdlLCBidXQgbm90IEZpcmVmb3gpLlxuICAgIGlmICh0aGlzLl9ob3N0LmNsYXNzTGlzdC5jb250YWlucygnb24tZHJhZy1zdGFydCcpKSB7XG4gICAgICB0aGlzLmRyYWdTb3VyY2VWaWV3VGFiLnNldCh0aGlzLl92aWV3VGFicygpLmZpbmQodmlld1RhYiA9PiB2aWV3VGFiLnZpZXdJZCA9PT0gZHJhZ0RhdGEudmlld0lkKSA/PyBudWxsKTtcbiAgICAgIHNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsIHsnLS3JtXBhcnQtYmFyLWRyYWctcGxhY2Vob2xkZXItd2lkdGgnOiBgJHtkcmFnRGF0YS52aWV3VGFiV2lkdGh9cHhgfSk7XG4gICAgfVxuXG4gICAgLy8gTG9jYXRlIHRoZSB0YWIgdGhlIHVzZXIgaXMgZHJhZ2dpbmcgb3Zlci5cbiAgICB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiLnNldCh0aGlzLmNvbXB1dGVEcm9wVGFyZ2V0KGV2ZW50KSk7XG5cbiAgICAvLyBEaXNhYmxlIHBvaW50ZXIgZXZlbnRzIG9uIHRoZSB0YWJiYXIgZm9yIGEgc21vb3RoZXIgZHJhZyBhbmQgZHJvcCBleHBlcmllbmNlIHdoZW4gcXVpY2tseSBzd2FwcGluZyB0YWJzLlxuICAgIHNldENzc0NsYXNzKHRoaXMuX2hvc3QsICdwb2ludGVyLWV2ZW50cy1kaXNhYmxlZCcpO1xuXG4gICAgLy8gU2V0IENTUyBjbGFzcyB0byBhbmltYXRlIGVudGVyaW5nIHRoZSB0YWJiYXIuXG4gICAgc2V0Q3NzQ2xhc3ModGhpcy5faG9zdCwgJ29uLWRyYWctZW50ZXInKTtcbiAgICB0aGlzLm9uRHJhZ0FuaW1hdGlvblN0YWJsZSgoKSA9PiB1bnNldENzc0NsYXNzKHRoaXMuX2hvc3QsICdvbi1kcmFnLWVudGVyJykpO1xuXG4gICAgLy8gSW5qZWN0IGRyYWcgc291cmNlIHdpZHRoIGludG8gQ1NTLlxuICAgIHNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsIHsnLS3JtXBhcnQtYmFyLWRyYWctc291cmNlLXdpZHRoJzogYCR7ZHJhZ0RhdGEudmlld1RhYldpZHRofXB4YH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgZHJhZ3MgYSB0YWIgb3V0IG9mIHRoaXMgdGFiYmFyLlxuICAgKi9cbiAgcHJpdmF0ZSBvblRhYmJhckRyYWdMZWF2ZShldmVudDogRHJhZ0V2ZW50KTogdm9pZCB7XG4gICAgLy8gU2V0IENTUyBjbGFzcyB0byBhbmltYXRlIGxlYXZpbmcgdGhlIHRhYmJhciwgYnV0IG5vdCB3aGVuIGNhbmNlbGluZyB0aGUgZHJhZyBvcGVyYXRpb24gZm9yIGluc3RhbnQgcmVzZXQuXG4gICAgLy8gUG9pbnRlciBjb29yZGluYXRlcyBhcmUgbm90IHNldCB3aGVuIHRoZSBkcmFnIG9wZXJhdGlvbiBpcyBjYW5jZWxlZCBvciB3aGVuIGRyYWdnaW5nIHRoZSB0YWIgb3V0IG9mIHRoZSB3aW5kb3cuXG4gICAgaWYgKGV2ZW50LnNjcmVlblggfHwgZXZlbnQuc2NyZWVuWSkge1xuICAgICAgc2V0Q3NzQ2xhc3ModGhpcy5faG9zdCwgJ29uLWRyYWctbGVhdmUnKTtcbiAgICAgIHRoaXMub25EcmFnQW5pbWF0aW9uU3RhYmxlKCgpID0+IHVuc2V0Q3NzQ2xhc3ModGhpcy5faG9zdCwgJ29uLWRyYWctbGVhdmUnKSk7XG4gICAgfVxuXG4gICAgLy8gQWN0aXZhdGUgdGhlIGFkamFjZW50IHRhYiwgb25seSBpZiB0aGUgZHJhZyBvcGVyYXRpb24gaXMgbm90IGNhbmNlbGVkLlxuICAgIC8vIFRoZSBkcmFnIGV2ZW50IGRvZXMgbm90IHByb3ZpZGUgaW5mb3JtYXRpb24gYWJvdXQgY2FuY2VsYXRpb24uIFRoZXJlZm9yZSwgd2Ugd2FpdCBmb3IgYSBtYWNyb3Rhc2ssIGNhbmNlbGluZyBpdCB3aGVuIHJlY2VpdmluZyBgZHJhZ2VuZGAsIGkuZS4sIHRoZSBkcmFnIG9wZXJhdGlvbiBoYXMgYmVlbiBjYW5jZWxlZC5cbiAgICBpZiAodGhpcy5kcmFnU291cmNlVmlld1RhYigpPy5hY3RpdmUpIHtcbiAgICAgIHRpbWVyKDApXG4gICAgICAgIC5waXBlKHRha2VVbnRpbChmcm9tRXZlbnQod2luZG93LCAnZHJhZ2VuZCcpKSlcbiAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl9yb3V0ZXIubmF2aWdhdGUobGF5b3V0ID0+IGxheW91dC5hY3RpdmF0ZUFkamFjZW50Vmlldyh0aGlzLmRyYWdTb3VyY2VWaWV3VGFiKCkhLnZpZXdJZCksIHtza2lwTG9jYXRpb25DaGFuZ2U6IHRydWV9KSk7XG4gICAgfVxuXG4gICAgLy8gQ2xlYW4gdXAgZHJhZyBzdGF0ZS5cbiAgICB0aGlzLnVuc2V0RHJhZ1N0YXRlKHt1bnNldERyYWdTb3VyY2U6IGZhbHNlLCB1bnNldERyYWdEYXRhOiBmYWxzZX0pO1xuICB9XG5cbiAgLyoqXG4gICAqIE1ldGhvZCBpbnZva2VkIHdoZW4gdGhlIHVzZXIgaXMgZHJhZ2dpbmcgYSB0YWIgb3ZlciB0aGlzIHRhYmJhci5cbiAgICovXG4gIHByaXZhdGUgb25UYWJiYXJEcmFnT3ZlcihldmVudDogRHJhZ0V2ZW50LCBkcmFnRGlzdGFuY2U6IG51bWJlciwgc2Nyb2xsRGlzdGFuY2U6IG51bWJlcik6IHZvaWQge1xuICAgIE5nWm9uZS5hc3NlcnROb3RJbkFuZ3VsYXJab25lKCk7XG4gICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gYWxsb3cgdmlldyBkcm9wXG5cbiAgICAvLyBMb2NhdGUgdGhlIHRhYiB0aGUgdXNlciBpcyBkcmFnZ2luZyBvdmVyLlxuICAgIC8vIC0gUnVuIGluIGFuaW1hdGlvbiBmcmFtZSBmb3IgYmV0dGVyIHBlcmZvcm1hbmNlLCBtb3N0IG5vdGljZWFibGUgb24gbG93ZXIgQ1BVIHBvd2VyLlxuICAgIC8vIC0gRG8gbm90IHdhaXQgZm9yIHRoZSBkcmFnIGFuaW1hdGlvbiB0byBjb21wbGV0ZSBmb3IgYSBzbW9vdGhlciBkcmFnIGFuZCBkcm9wIGV4cGVyaWVuY2Ugd2hlbiBxdWlja2x5IG1vdmluZyB0aGUgdGFiIGluIHRoZSB0YWJiYXIuXG4gICAgcmVxdWVzdEFuaW1hdGlvbkZyYW1lKCgpID0+IHtcbiAgICAgIC8vIFNraXAgaWYgdGhlIGRyYWcgb3BlcmF0aW9uIGhhcyBlbmRlZC5cbiAgICAgIGlmICh0aGlzLl92aWV3RHJhZ1NlcnZpY2UuaXNEcmFnT3ZlclRhYmJhciAhPT0gdGhpcy5wYXJ0LmlkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gSWdub3JlIHRoZSBkcmFnIGRpc3RhbmNlIGlmIGBkcmFnLWVudGVyYCBhbmltYXRpb24gaXMgaW4gcHJvZ3Jlc3MgdG8gYXZvaWQgaW5jb3JyZWN0IGRyb3AgdGFyZ2V0IGNvbXB1dGF0aW9uIHdoZW4gZHJhZ2dpbmcgYSB0YWIgZnJvbSB0aGUgbGVmdC5cbiAgICAgIGlmICh0aGlzLl9ob3N0LmNsYXNzTGlzdC5jb250YWlucygnb24tZHJhZy1lbnRlcicpKSB7XG4gICAgICAgIHRoaXMuZHJvcFRhcmdldFZpZXdUYWIuc2V0KHRoaXMuY29tcHV0ZURyb3BUYXJnZXQoZXZlbnQsIDApKTtcbiAgICAgIH1cbiAgICAgIC8vIENvbXB1dGUgZHJvcCB0YXJnZXQgb25seSB3aGVuIG1vdmluZyB0aGUgZHJhZyBwb2ludGVyIHRvIHByZXZlbnQgdGFicyBmcm9tIHNsaWRpbmcgYmFjayBhbmQgZm9ydGggKHdoaWxlIGFuaW1hdGlvbiBpcyBpbiBwcm9ncmVzcylcbiAgICAgIGVsc2UgaWYgKGRyYWdEaXN0YW5jZSkge1xuICAgICAgICB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiLnNldCh0aGlzLmNvbXB1dGVEcm9wVGFyZ2V0KGV2ZW50LCBkcmFnRGlzdGFuY2UpKTtcbiAgICAgIH1cbiAgICAgIC8vIENvbXB1dGUgZHJvcCB0YXJnZXQgd2hlbiBzY3JvbGxpbmcgdGhlIHZpZXdwb3J0LCBpLmUuLCBub3QgbW92aW5nIHRoZSBkcmFnIHBvaW50ZXIgYnV0IHNjcm9sbGluZyB0aGUgdmlld3BvcnQgYmVjYXVzZSBwbGFjZWQgdGhlIGRyYWcgcG9pbnRlciBhdCB0aGUgdmlld3BvcnQgZWRnZXMuXG4gICAgICBlbHNlIGlmIChzY3JvbGxEaXN0YW5jZSkge1xuICAgICAgICB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiLnNldCh0aGlzLmNvbXB1dGVEcm9wVGFyZ2V0KGV2ZW50LCBzY3JvbGxEaXN0YW5jZSkpO1xuICAgICAgfVxuXG4gICAgICAvLyBTZXQgQ1NTIGNsYXNzIHRvIGFuaW1hdGUgZHJhZ2dpbmcgb3ZlciB0aGUgdGFiYmFyLlxuICAgICAgc2V0Q3NzQ2xhc3ModGhpcy5faG9zdCwgJ2RyYWctb3ZlcicpO1xuXG4gICAgICAvLyBDYWxjdWxhdGUgdGhlIG5ldyBzaXplIG9mIHRoZSBkcmFnIHNvdXJjZSBwbGFjZWhvbGRlci5cbiAgICAgIC8vIFRoZSBwbGFjZWhvbGRlciBleHBhbmRzIHRoZSB2aWV3cG9ydCB3aGVuIGRyYWdnaW5nIGEgdGFiIHRvIHRoZSByaWdodCwgbW92aW5nIHBhcnQgYWN0aW9ucyBhbG9uZyB3aXRoIHRoZSBkcmFnb3ZlciBldmVudC5cbiAgICAgIHNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsIHsnLS3JtXBhcnQtYmFyLWRyYWctcGxhY2Vob2xkZXItd2lkdGgnOiBgJHt0aGlzLmNhbGN1bGF0ZURyYWdQbGFjZWhvbGRlcldpZHRoKGV2ZW50KX1weGB9KTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBNZXRob2QgaW52b2tlZCB3aGVuIHRoZSB1c2VyIGRyb3BzIGEgdGFiIGluIHRoaXMgdGFiYmFyLlxuICAgKi9cbiAgcHJpdmF0ZSBhc3luYyBvblRhYmJhckRyb3AoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgY29uc3QgZHJhZ0RhdGEgPSB0aGlzLl9kcmFnRGF0YSE7XG4gICAgY29uc3QgZHJvcFRhcmdldFZpZXdUYWIgPSB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiKCkhO1xuICAgIGNvbnN0IGRyb3BQb3NpdGlvbiA9IGRyb3BUYXJnZXRWaWV3VGFiID09PSAnZW5kJyA/ICdlbmQnIDogdGhpcy5fdmlld1RhYnMoKS5pbmRleE9mKGRyb3BUYXJnZXRWaWV3VGFiKTtcblxuICAgIHRoaXMuX3ZpZXdEcmFnU2VydmljZS5kaXNwYXRjaFZpZXdNb3ZlRXZlbnQoe1xuICAgICAgc291cmNlOiB7XG4gICAgICAgIHdvcmtiZW5jaElkOiBkcmFnRGF0YS53b3JrYmVuY2hJZCxcbiAgICAgICAgcGFydElkOiBkcmFnRGF0YS5wYXJ0SWQsXG4gICAgICAgIHZpZXdJZDogZHJhZ0RhdGEudmlld0lkLFxuICAgICAgICBhbHRlcm5hdGl2ZVZpZXdJZDogZHJhZ0RhdGEuYWx0ZXJuYXRpdmVWaWV3SWQsXG4gICAgICAgIHZpZXdVcmxTZWdtZW50czogZHJhZ0RhdGEudmlld1VybFNlZ21lbnRzLFxuICAgICAgICBuYXZpZ2F0aW9uSGludDogZHJhZ0RhdGEubmF2aWdhdGlvbkhpbnQsXG4gICAgICAgIG5hdmlnYXRpb25EYXRhOiBkcmFnRGF0YS5uYXZpZ2F0aW9uRGF0YSxcbiAgICAgICAgY2xhc3NMaXN0OiBkcmFnRGF0YS5jbGFzc0xpc3QsXG4gICAgICB9LFxuICAgICAgdGFyZ2V0OiB7XG4gICAgICAgIHdvcmtiZW5jaElkOiB0aGlzLl93b3JrYmVuY2hJZCxcbiAgICAgICAgcG9zaXRpb246IGRyb3BQb3NpdGlvbixcbiAgICAgICAgZWxlbWVudElkOiB0aGlzLnBhcnQuaWQsXG4gICAgICB9LFxuICAgICAgZHJhZ0RhdGE6IGRyYWdEYXRhLFxuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIExvY2F0ZXMgdGhlIHRhYiBiZWZvcmUgd2hpY2ggdGhlIGRyYWdnZWQgdGFiIGlzIHRvIGJlIGluc2VydGVkIHdoZW4gaXQgaXMgZHJvcHBlZC4gRHJhZ2dpbmcgYmV5b25kIHRoZSBsYXN0IHRhYiByZXR1cm5zIGBlbmRgLlxuICAgKi9cbiAgcHJpdmF0ZSBjb21wdXRlRHJvcFRhcmdldChldmVudDogRHJhZ0V2ZW50LCBkcmFnRGlzdGFuY2VYID0gMCk6IFZpZXdUYWJDb21wb25lbnQgfCAnZW5kJyB7XG4gICAgY29uc3QgZHJhZ0ltYWdlID0gdGhpcy5fdmlld1RhYkRyYWdJbWFnZVJlbmRlcmVyLmNhbGN1bGF0ZURyYWdJbWFnZVJlY3QodGhpcy5fZHJhZ0RhdGEhLCBldmVudCk7XG4gICAgY29uc3Qgdmlld1RhYnMgPSB0aGlzLl92aWV3VGFicygpLmZpbHRlcih2aWV3VGFiID0+IHZpZXdUYWIgIT09IHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIoKSk7XG5cbiAgICBmb3IgKGNvbnN0IHZpZXdUYWIgb2Ygdmlld1RhYnMpIHtcbiAgICAgIGNvbnN0IHtsZWZ0LCB3aWR0aH0gPSB2aWV3VGFiLmJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuICAgICAgY29uc3Qgdmlld1RhYkhDZW50ZXIgPSBsZWZ0ICsgKHdpZHRoIC8gMik7XG5cbiAgICAgIC8vIE1vdmluZyB0aGUgcG9pbnRlciB0byB0aGUgbGVmdC5cbiAgICAgIGlmIChkcmFnRGlzdGFuY2VYIDw9IDAgJiYgZHJhZ0ltYWdlLmxlZnQgPCB2aWV3VGFiSENlbnRlcikge1xuICAgICAgICByZXR1cm4gdmlld1RhYjtcbiAgICAgIH1cbiAgICAgIC8vIE1vdmluZyB0aGUgcGludGVyIHRvIHRoZSByaWdodC5cbiAgICAgIGlmIChkcmFnRGlzdGFuY2VYID4gMCAmJiBkcmFnSW1hZ2UucmlnaHQgPCB2aWV3VGFiSENlbnRlcikge1xuICAgICAgICByZXR1cm4gdmlld1RhYjtcbiAgICAgIH1cbiAgICB9XG4gICAgcmV0dXJuICdlbmQnO1xuICB9XG5cbiAgLyoqXG4gICAqIENyZWF0ZXMgdGhlIGZ1bmN0aW9uIGZvciBzbmFwcGluZyB0aGUgZHJhZyBpbWFnZSB0byB0aGUgdGFiYmFyIHdoZW4gZHJhZ2dpbmcgbmVhciBpdC5cbiAgICovXG4gIHByaXZhdGUgY3JlYXRlRHJhZ0ltYWdlQ29uc3RyYWluRm4oKTogQ29uc3RyYWluRm4ge1xuICAgIHJldHVybiAoZHJhZ0ltYWdlOiBET01SZWN0KTogRE9NUmVjdCA9PiBuZXcgRE9NUmVjdChcbiAgICAgIGNsYW1wKGRyYWdJbWFnZS54LCB7XG4gICAgICAgIG1pbjogdGhpcy5faG9zdEJvdW5kaW5nQ2xpZW50UmVjdCgpLmxlZnQgKyB0aGlzLl90YWJiYXJJbmRlbnQubGVmdCxcbiAgICAgICAgbWF4OiB0aGlzLl9ob3N0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCArIHRoaXMuX21heFZpZXdwb3J0V2lkdGgoKSAtIGRyYWdJbWFnZS53aWR0aCAtIHRoaXMuX3RhYmJhckluZGVudC5yaWdodCxcbiAgICAgIH0pLFxuICAgICAgdGhpcy5fdmlld3BvcnRCb3VuZGluZ0JveCgpLnRvcCxcbiAgICAgIGRyYWdJbWFnZS53aWR0aCxcbiAgICAgIHRoaXMuX3ZpZXdwb3J0Qm91bmRpbmdCb3goKS5oZWlnaHQsIC8vIGZpdCBpbnRvIHRhYmJhciwgZS5nLiwgd2hlbiBkcmFnZ2luZyBhIHRhYiBpbnRvIGEgdGFiYmFyIG9mIGEgZGlmZmVyZW50IGhlaWdodFxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgbWF4aW11bSB3aWR0aCBvZiB0aGUgdGFiYmFyIHZpZXdwb3J0IGJlZm9yZSBhbiBvdmVyZmxvdyB3b3VsZCBvY2N1ci5cbiAgICogVXNlIHRvIGNvbnN0cmFpbiB0aGUgZHJhZyBpbWFnZSB0byB0aGUgdGFiYmFyIGJvdW5kcy5cbiAgICovXG4gIHByaXZhdGUgY2FsY3VsYXRlTWF4Vmlld3BvcnRXaWR0aCgpOiBTaWduYWw8bnVtYmVyPiB7XG4gICAgY29uc3QgZmlsbGVyRGltZW5zaW9uID0gZGltZW5zaW9uKHRoaXMuX2ZpbGxlckVsZW1lbnQpO1xuICAgIHJldHVybiBjb21wdXRlZCgoKSA9PiB0aGlzLl92aWV3cG9ydEJvdW5kaW5nQm94KCkud2lkdGggKyBmaWxsZXJEaW1lbnNpb24oKS5vZmZzZXRXaWR0aCk7XG4gIH1cblxuICAvKipcbiAgICogQ2FsY3VsYXRlcyB0aGUgd2lkdGggZm9yIHRoZSBkcmFnIHBsYWNlaG9sZGVyLlxuICAgKlxuICAgKiBUaGUgcGxhY2Vob2xkZXIgZXhwYW5kcyB0aGUgdmlld3BvcnQgd2hlbiBkcmFnZ2luZyBhIHRhYiB0byB0aGUgcmlnaHQsIG1vdmluZyBwYXJ0IGFjdGlvbnMgYWxvbmcgd2l0aCB0aGUgZHJhZ292ZXIgZXZlbnQuXG4gICAqXG4gICAqIENhbGN1bGF0aW9uOlxuICAgKiAtIFdoZW4gZHJhZ2dpbmcgb3ZlciB0YWJzLCB0aGUgd2lkdGggaXMgZXF1YWwgdG8gdGhlIHdpZHRoIG9mIHRoZSBkcmFnIHNvdXJjZS5cbiAgICogLSBXaGVuIGRyYWdnaW5nIHRvIHRoZSByaWdodCBvZiB0aGUgbGFzdCB0YWIsIHRoZSB3aWR0aCBvZiB0aGUgcGxhY2Vob2xkZXIgaXMgdGhlIGRpc3RhbmNlIGJldHdlZW4gdGhlIGxhc3QgdGFiIGFuZCB0aGUgcG9zaXRpb24gb2YgdGhlIGRyYWcgcG9pbnRlci5cbiAgICovXG4gIHByaXZhdGUgY2FsY3VsYXRlRHJhZ1BsYWNlaG9sZGVyV2lkdGgoZXZlbnQ6IERyYWdFdmVudCk6IG51bWJlciB7XG4gICAgY29uc3Qgdmlld0RyYWdJbWFnZVJlY3QgPSB0aGlzLl92aWV3VGFiRHJhZ0ltYWdlUmVuZGVyZXIuY2FsY3VsYXRlRHJhZ0ltYWdlUmVjdCh0aGlzLl9kcmFnRGF0YSEsIGV2ZW50KTtcbiAgICBjb25zdCBsYXN0Vmlld1RhYiA9IHRoaXMuX3ZpZXdUYWJzKCkuZmlsdGVyKHZpZXdUYWIgPT4gdmlld1RhYiAhPT0gdGhpcy5kcmFnU291cmNlVmlld1RhYigpKS5hdCgtMSk7XG4gICAgY29uc3QgbGFzdFZpZXdUYWJSaWdodCA9IGxhc3RWaWV3VGFiPy5ib3VuZGluZ0NsaWVudFJlY3QoKS5yaWdodCA/PyB0aGlzLl9ob3N0Qm91bmRpbmdDbGllbnRSZWN0KCkubGVmdCArIHRoaXMuX3RhYmJhckluZGVudC5sZWZ0O1xuICAgIHJldHVybiBNYXRoLm1heChsYXN0Vmlld1RhYlJpZ2h0ICsgdmlld0RyYWdJbWFnZVJlY3Qud2lkdGgsIHZpZXdEcmFnSW1hZ2VSZWN0LnJpZ2h0KSAtIGxhc3RWaWV3VGFiUmlnaHQ7XG4gIH1cblxuICAvKipcbiAgICogSW5kaWNhdGVzIHdoZXRoZXIgQ1NTIGFuaW1hdGlvbnMgaGF2ZSBmaW5pc2hlZCB3aGVuIGRyYWdnaW5nIGEgdGFiIG92ZXIgdGhlIHRhYmJhci5cbiAgICogVGhlIGFuaW1hdGlvbiBpcyBjb25zaWRlcmVkIHN0YWJsZSB3aGVuIGFsbCB0YWJzIGhhdmUgbW92ZWQgdG8gdGhlaXIgZmluYWwgcG9zaXRpb24uXG4gICAqL1xuICBwcml2YXRlIGlzRHJhZ0FuaW1hdGlvblN0YWJsZSgpOiBib29sZWFuIHtcbiAgICBjb25zdCBkcm9wVGFyZ2V0Vmlld1RhYiA9IHRoaXMuZHJvcFRhcmdldFZpZXdUYWIoKTtcbiAgICBpZiAodGhpcy5fdmlld0RyYWdTZXJ2aWNlLmlzRHJhZ092ZXJUYWJiYXIgIT09IHRoaXMucGFydC5pZCkge1xuICAgICAgcmV0dXJuIHRoaXMuX3ZpZXdUYWJzKCkuZXZlcnkodmlld1RhYiA9PiBnZXRDc3NUcmFuc2xhdGlvbih2aWV3VGFiLmhvc3QpLnRyYW5zbGF0ZVggPT09ICdub25lJyk7XG4gICAgfVxuXG4gICAgY29uc3Qgdmlld1RhYnMgPSB0aGlzLl92aWV3VGFicygpLmZpbHRlcih2aWV3VGFiID0+IHZpZXdUYWIgIT09IHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIoKSk7XG4gICAgY29uc3QgZHJvcFRhcmdldEluZGV4ID0gZHJvcFRhcmdldFZpZXdUYWIgPT09ICdlbmQnID8gdmlld1RhYnMubGVuZ3RoIDogdmlld1RhYnMuaW5kZXhPZihkcm9wVGFyZ2V0Vmlld1RhYiEpO1xuICAgIGNvbnN0IGRyYWdTb3VyY2VXaWR0aCA9IHRoaXMuX2RyYWdEYXRhIS52aWV3VGFiV2lkdGg7XG5cbiAgICByZXR1cm4gdmlld1RhYnMuZXZlcnkoKHZpZXdUYWIsIGkpID0+IHtcbiAgICAgIGNvbnN0IHZpZXdUYWJUcmFuc2xhdGVYID0gZ2V0Q3NzVHJhbnNsYXRpb24odmlld1RhYi5ob3N0KS50cmFuc2xhdGVYO1xuICAgICAgLy8gRXhwZWN0IHRhYnMgcHJlY2VkaW5nIHRoZSBkcm9wIHRhcmdldCBub3QgdG8gYmUgc2hpZnRlZCB0byB0aGUgcmlnaHQuXG4gICAgICBpZiAoaSA8IGRyb3BUYXJnZXRJbmRleCAmJiB2aWV3VGFiVHJhbnNsYXRlWCAhPT0gJ25vbmUnKSB7XG4gICAgICAgIHJldHVybiBmYWxzZTtcbiAgICAgIH1cbiAgICAgIC8vIEV4cGVjdCBkcm9wIHRhcmdldCBhbmQgdGFicyBmb2xsb3dpbmcgdGhlIGRyb3AgdGFyZ2V0IHRvIGJlIHNoaWZ0ZWQgdG8gdGhlIHJpZ2h0LlxuICAgICAgaWYgKGkgPj0gZHJvcFRhcmdldEluZGV4ICYmIE1hdGguZmxvb3IoTnVtYmVyKHZpZXdUYWJUcmFuc2xhdGVYKSkgIT09IE1hdGguZmxvb3IoZHJhZ1NvdXJjZVdpZHRoKSkgeyAvLyBjb21wYXJlIGZsb29yZWQgbnVtYmVycyBiZWNhdXNlIGB0cmFuc2xhdGVYYCBpcyBub3QgcHJlY2lzZVxuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgICByZXR1cm4gdHJ1ZTtcbiAgICB9KTtcbiAgfVxuXG4gIC8qKlxuICAgKiBDbGVhbnMgdXAgdGhlIGRyYWcgc3RhdGUsIHVuc2V0dGluZyBkcmFnIGRhdGEgYW5kIGRyYWcgc291cmNlIGJhc2VkIG9uIHByb3ZpZGVkIG9wdGlvbnMuXG4gICAqL1xuICBwcml2YXRlIHVuc2V0RHJhZ1N0YXRlKG9wdGlvbnM/OiB7dW5zZXREcmFnU291cmNlPzogZmFsc2U7IHVuc2V0RHJhZ0RhdGE/OiBmYWxzZX0pOiB2b2lkIHtcbiAgICB0aGlzLmRyb3BUYXJnZXRWaWV3VGFiLnNldChudWxsKTtcbiAgICB0aGlzLl9vblVuc2V0RHJhZ1N0YXRlLnNldCgpO1xuICAgIHRoaXMuX3ZpZXdUYWJEcmFnSW1hZ2VSZW5kZXJlci51bnNldENvbnN0cmFpbkRyYWdJbWFnZVJlY3RGbih0aGlzLl9jb25zdHJhaW5GbiEpO1xuICAgIHRoaXMuX3ZpZXdEcmFnU2VydmljZS5zaWduYWxUYWJiYXJEcmFnTGVhdmUodGhpcy5wYXJ0LmlkKTtcbiAgICB0aGlzLl9jb25zdHJhaW5GbiA9IG51bGw7XG5cbiAgICB1bnNldENzc0NsYXNzKHRoaXMuX2hvc3QsICdkcmFnLW92ZXInLCAncG9pbnRlci1ldmVudHMtZGlzYWJsZWQnKTtcbiAgICB1bnNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsICctLcm1cGFydC1iYXItZHJhZy1zb3VyY2Utd2lkdGgnLCAnLS3JtXBhcnQtYmFyLWRyYWctcGxhY2Vob2xkZXItd2lkdGgnKTtcblxuICAgIGlmIChvcHRpb25zPy51bnNldERyYWdTb3VyY2UgPz8gdHJ1ZSkge1xuICAgICAgdGhpcy5kcmFnU291cmNlVmlld1RhYi5zZXQobnVsbCk7XG4gICAgfVxuICAgIGlmIChvcHRpb25zPy51bnNldERyYWdEYXRhID8/IHRydWUpIHtcbiAgICAgIHRoaXMuX2RyYWdEYXRhID0gbnVsbDtcbiAgICB9XG4gIH1cblxuICAvKipcbiAgICogRXhlY3V0ZXMgZ2l2ZW4gZnVuY3Rpb24gd2hlbiB0aGUgZHJhZyBhbmltYXRpb24gaGFzIGZpbmlzaGVkLCBpLmUuLCB0YWJzIGhhdmUgdHJhbnNpdGlvbmVkIHRvIHRoZWlyIGZpbmFsIHBvc2l0aW9uLlxuICAgKi9cbiAgcHJpdmF0ZSBvbkRyYWdBbmltYXRpb25TdGFibGUoY2FsbGJhY2s6ICgpID0+IHZvaWQpOiB2b2lkIHtcbiAgICBpZiAoTmdab25lLmlzSW5Bbmd1bGFyWm9uZSgpKSB7XG4gICAgICB0aGlzLl96b25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHRoaXMub25EcmFnQW5pbWF0aW9uU3RhYmxlKGNhbGxiYWNrKSk7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB0aGlzLmlzRHJhZ0FuaW1hdGlvblN0YWJsZSgpID8gY2FsbGJhY2soKSA6IHRoaXMub25EcmFnQW5pbWF0aW9uU3RhYmxlKGNhbGxiYWNrKSk7XG4gIH1cblxuICAvKipcbiAgICogU2Nyb2xscyB0aGUgdGFiIG9mIHRoZSBhY3RpdmUgdmlldyBpbnRvIHZpZXcuXG4gICAqL1xuICBwcml2YXRlIGluc3RhbGxBY3RpdmVWaWV3U2Nyb2xsZXIoKTogdm9pZCB7XG4gICAgZWZmZWN0KCgpID0+IHtcbiAgICAgIC8vIFRyYWNrIHRoZSBhY3RpdmUgdmlldy5cbiAgICAgIGNvbnN0IGFjdGl2ZVZpZXdJZCA9IHRoaXMucGFydC5hY3RpdmVWaWV3SWQoKTtcbiAgICAgIC8vIFRoZXJlIG1heSBiZSBubyBhY3RpdmUgdmlldywgZS5nLiwgaWYgbm8gdmlldyBoYXMgYmVlbiBhY3RpdmF0ZWQsIG9yIHdoZW4gZHJhZ2dpbmcgdGhlIGxhc3QgdmlldyBvdXQgb2YgdGhlIHRhYmJhci5cbiAgICAgIGlmICghYWN0aXZlVmlld0lkKSB7XG4gICAgICAgIHJldHVybjtcbiAgICAgIH1cblxuICAgICAgLy8gRG8gbm90IHRyYWNrIHJlbmRlcmVkIHRhYnMgaW4gZ2VuZXJhbCB0byBwcmV2ZW50IHVud2FudGVkIHNjcm9sbGluZyB3aGVuIG9wZW5pbmcgb3IgY2xvc2luZyBpbmFjdGl2ZSB0YWJzLlxuICAgICAgY29uc3Qgdmlld1RhYnMgPSB1bnRyYWNrZWQoKCkgPT4gdGhpcy5fdmlld1RhYnMoKSk7XG5cbiAgICAgIC8vIEdldCBhIHJlZmVyZW5jZSB0byB0aGUgY3VycmVudGx5IHJlbmRlcmVkIGFjdGl2ZSB0YWIsIHdhaXRpbmcgaWYgbmVjZXNzYXJ5IGJ5IHRyYWNraW5nIHRoZSByZW5kZXJlZCB0YWJzLlxuICAgICAgY29uc3QgYWN0aXZlVmlld1RhYiA9IHZpZXdUYWJzLmZpbmQodmlld1RhYiA9PiB2aWV3VGFiLnZpZXdJZCA9PT0gYWN0aXZlVmlld0lkKTtcbiAgICAgIGlmICghYWN0aXZlVmlld1RhYikge1xuICAgICAgICB0aGlzLl92aWV3VGFicygpOyAvLyBUcmFjayByZW5kZXJlZCB0YWJzIHRvIHJlLWV4ZWN1dGUgb25jZSByZW5kZXJlZC5cbiAgICAgICAgcmV0dXJuO1xuICAgICAgfVxuXG4gICAgICAvLyBUcmFjayBuYXZpZ2F0aW9uIG9mIHRoZSBhY3RpdmUgdmlldywgc2Nyb2xsaW5nIGl0cyB0YWIgaW50byB2aWV3IGlmIG5lY2Vzc2FyeS5cbiAgICAgIGFjdGl2ZVZpZXdUYWIudmlldygpLm5hdmlnYXRpb25JZCgpO1xuXG4gICAgICAvLyBUcmFjayB1bnNldHRpbmcgZHJhZyBzdGF0ZSB0byBlbnN1cmUgdGhlIGFjdGl2ZSB2aWV3IGlzIHNjcm9sbGVkIGludG8gdmlldyBhZnRlciBkcm9wIG9yIGNhbmNlbC5cbiAgICAgIHRoaXMuX29uVW5zZXREcmFnU3RhdGUoKTtcblxuICAgICAgLy8gU2Nyb2xsIHRoZSB0YWIgaW50byB2aWV3IGlmIHNjcm9sbGVkIG91dCBvZiB2aWV3LlxuICAgICAgdW50cmFja2VkKCgpID0+IHJlcXVlc3RBbmltYXRpb25GcmFtZSgoKSA9PiB7XG4gICAgICAgIGlmICghdGhpcy5fdmlld3BvcnRDb21wb25lbnQoKS5pc0VsZW1lbnRJblZpZXcoYWN0aXZlVmlld1RhYi5ob3N0LCAnZnVsbCcpKSB7XG4gICAgICAgICAgdGhpcy5fdmlld3BvcnRDb21wb25lbnQoKS5zY3JvbGxJbnRvVmlldyhhY3RpdmVWaWV3VGFiLmhvc3QpO1xuICAgICAgICB9XG4gICAgICB9KSk7XG4gICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogVXBkYXRlcyB7QGxpbmsgybVXb3JrYmVuY2hWaWV3fSB3aGVuIGl0cyB0YWIgaXMgc2Nyb2xsZWQgaW50byB2aWV3LlxuICAgKi9cbiAgcHJpdmF0ZSBpbnN0YWxsU2Nyb2xsZWRJbnRvVmlld1VwZGF0ZXIoKTogdm9pZCB7XG4gICAgdGhpcy5fdmlld3BvcnRDaGFuZ2UkXG4gICAgICAucGlwZShcbiAgICAgICAgbWFwKCgpID0+IHRoaXMuX3ZpZXdUYWJzKCkpLFxuICAgICAgICBmaWx0ZXJBcnJheSh2aWV3VGFiID0+IHZpZXdUYWIgIT09IHRoaXMuZHJhZ1NvdXJjZVZpZXdUYWIoKSksIC8vIHNraXAgZHJhZyBzb3VyY2UgYXMgYWx3YXlzIHNjcm9sbGVkIG91dCBvZiB2aWV3XG4gICAgICAgIG1lcmdlTWFwKHZpZXdUYWJzID0+IGZyb20odmlld1RhYnMpKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKHZpZXdUYWIgPT4ge1xuICAgICAgICB2aWV3VGFiLnZpZXcoKS5zY3JvbGxlZEludG9WaWV3ID0gdGhpcy5fdmlld3BvcnRDb21wb25lbnQoKS5pc0VsZW1lbnRJblZpZXcodmlld1RhYi5ob3N0LCAnZnVsbCcpO1xuICAgICAgfSk7XG4gIH1cblxuICAvKipcbiAgICogU3Vic2NyaWJlcyB0byBkcmFnIGV2ZW50cy5cbiAgICovXG4gIHByaXZhdGUgaW5zdGFsbFZpZXdEcmFnTGlzdGVuZXIoKTogdm9pZCB7XG4gICAgY29uc3Qgem9uZSA9IGluamVjdChOZ1pvbmUpO1xuXG4gICAgLy8gU3Vic2NyaWJlIHRvIGRyYWcgZXZlbnRzIHJlbGV2YW50IGZvciB0aGlzIHRhYmJhci5cbiAgICB0aGlzLl92aWV3RHJhZ1NlcnZpY2Uudmlld0RyYWckKHRoaXMuX2hvc3QpXG4gICAgICAucGlwZShcbiAgICAgICAgc3Vic2NyaWJlSW4oZm4gPT4gem9uZS5ydW5PdXRzaWRlQW5ndWxhcihmbikpLFxuICAgICAgICBjYWxjdWxhdGVEaXN0YW5jZSgoKSA9PiB0aGlzLl92aWV3cG9ydENvbXBvbmVudCgpKSwgLy8gcHJvdmlkZSB2aWV3cG9ydCBsYXppbHkgYmVjYXVzZSBub3QgaW5qZWN0ZWQgeWV0XG4gICAgICAgIHRha2VVbnRpbERlc3Ryb3llZCgpLFxuICAgICAgKVxuICAgICAgLnN1YnNjcmliZSgoe2V2ZW50LCBkcmFnRGlzdGFuY2UsIHNjcm9sbERpc3RhbmNlfSkgPT4ge1xuICAgICAgICBzd2l0Y2ggKGV2ZW50LnR5cGUpIHtcbiAgICAgICAgICBjYXNlICdkcmFnc3RhcnQnOlxuICAgICAgICAgICAgdGhpcy5vblRhYkRyYWdTdGFydCgpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJhZ2VuZCc6XG4gICAgICAgICAgICB0aGlzLm9uVGFiRHJhZ0VuZChldmVudCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdkcmFnZW50ZXInOlxuICAgICAgICAgICAgdGhpcy5vblRhYmJhckRyYWdFbnRlcihldmVudCk7XG4gICAgICAgICAgICBicmVhaztcbiAgICAgICAgICBjYXNlICdkcmFnb3Zlcic6XG4gICAgICAgICAgICB0aGlzLm9uVGFiYmFyRHJhZ092ZXIoZXZlbnQsIGRyYWdEaXN0YW5jZSwgc2Nyb2xsRGlzdGFuY2UpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJhZ2xlYXZlJzpcbiAgICAgICAgICAgIHRoaXMub25UYWJiYXJEcmFnTGVhdmUoZXZlbnQpO1xuICAgICAgICAgICAgYnJlYWs7XG4gICAgICAgICAgY2FzZSAnZHJvcCc6XG4gICAgICAgICAgICB0aGlzLm9uVGFiYmFyRHJvcCgpLnRoZW4oKTtcbiAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICB9XG4gICAgICB9KTtcblxuICAgIC8vIEdldCBub3RpZmllZCB3aGVuIGEgdmlldyBoYXMgbW92ZWQgaW4gdGhlIGxheW91dC5cbiAgICB0aGlzLl92aWV3RHJhZ1NlcnZpY2Uudmlld01vdmVkJFxuICAgICAgLnBpcGUoXG4gICAgICAgIHN1YnNjcmliZUluKGZuID0+IHpvbmUucnVuT3V0c2lkZUFuZ3VsYXIoZm4pKSxcbiAgICAgICAgdGFrZVVudGlsRGVzdHJveWVkKCksXG4gICAgICApXG4gICAgICAuc3Vic2NyaWJlKGV2ZW50ID0+IHRoaXMub25UYWJNb3ZlZChldmVudCkpO1xuXG4gICAgLyoqXG4gICAgICogQ2FsY3VsYXRlcyB0aGUgZGlzdGFuY2UgdGhlIGRyYWcgcG9pbnRlciBhbmQgdmlld3BvcnQgaGF2ZSBtb3ZlZCBzaW5jZSB0aGUgbGFzdCBkcmFnIGV2ZW50LlxuICAgICAqL1xuICAgIGZ1bmN0aW9uIGNhbGN1bGF0ZURpc3RhbmNlKHZpZXdwb3J0OiAoKSA9PiBTY2lWaWV3cG9ydENvbXBvbmVudCk6IE9wZXJhdG9yRnVuY3Rpb248RHJhZ0V2ZW50LCBEcmFnRXZlbnRQbHVzRGlzdGFuY2U+IHtcbiAgICAgIHJldHVybiBzb3VyY2UkID0+IG5ldyBPYnNlcnZhYmxlPERyYWdFdmVudFBsdXNEaXN0YW5jZT4ob2JzZXJ2ZXIgPT4ge1xuICAgICAgICBsZXQgbGFzdFNjcmVlblg6IG51bWJlciB8IHVuZGVmaW5lZDtcbiAgICAgICAgbGV0IGxhc3RTY3JvbGxMZWZ0OiBudW1iZXIgfCB1bmRlZmluZWQ7XG5cbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gc291cmNlJC5zdWJzY3JpYmUoZXZlbnQgPT4ge1xuICAgICAgICAgIG9ic2VydmVyLm5leHQoe1xuICAgICAgICAgICAgZXZlbnQsXG4gICAgICAgICAgICBkcmFnRGlzdGFuY2U6IGV2ZW50LnNjcmVlblggLSAobGFzdFNjcmVlblggPz8gZXZlbnQuc2NyZWVuWCksXG4gICAgICAgICAgICBzY3JvbGxEaXN0YW5jZTogdmlld3BvcnQoKS5zY3JvbGxMZWZ0IC0gKGxhc3RTY3JvbGxMZWZ0ID8/IHZpZXdwb3J0KCkuc2Nyb2xsTGVmdCksXG4gICAgICAgICAgfSk7XG4gICAgICAgICAgbGFzdFNjcmVlblggPSBldmVudC5zY3JlZW5YO1xuICAgICAgICAgIGxhc3RTY3JvbGxMZWZ0ID0gdmlld3BvcnQoKS5zY3JvbGxMZWZ0O1xuICAgICAgICB9KTtcbiAgICAgICAgcmV0dXJuICgpID0+IHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgICAgfSk7XG4gICAgfVxuICB9XG5cbiAgLyoqXG4gICAqIEVtaXRzIG9uIHtAbGluayBfdmlld3BvcnRDaGFuZ2UkfSB3aGVuIHRoZSB2aWV3cG9ydCBzaXplIG9yIHNjcm9sbCBwb3NpdGlvbiBjaGFuZ2VzLlxuICAgKi9cbiAgcHJpdmF0ZSBpbnN0YWxsVmlld3BvcnRDaGFuZ2VUcmFja2VyKCk6IHZvaWQge1xuICAgIGNvbnN0IHZpZXdwb3J0U2l6ZSA9IGRpbWVuc2lvbihjb21wdXRlZCgoKSA9PiB0aGlzLl92aWV3cG9ydENvbXBvbmVudEVsZW1lbnQoKS5uYXRpdmVFbGVtZW50KSk7XG4gICAgY29uc3Qgdmlld3BvcnRDbGllbnRTaXplID0gZGltZW5zaW9uKGNvbXB1dGVkKCgpID0+IHRoaXMuX3ZpZXdwb3J0Q29tcG9uZW50KCkudmlld3BvcnRDbGllbnRFbGVtZW50KSk7XG4gICAgY29uc3Qgem9uZSA9IGluamVjdChOZ1pvbmUpO1xuXG4gICAgLy8gRGV0ZWN0IHJlc2l6aW5nLlxuICAgIGVmZmVjdCgoKSA9PiB7XG4gICAgICAvLyBUcmFjayB2aWV3cG9ydCBhbmQgdmlld3BvcnQgY2xpZW50IHNpemVzLlxuICAgICAgdmlld3BvcnRTaXplKCk7XG4gICAgICB2aWV3cG9ydENsaWVudFNpemUoKTtcbiAgICAgIHVudHJhY2tlZCgoKSA9PiB0aGlzLl92aWV3cG9ydENoYW5nZSQubmV4dCgpKTtcbiAgICB9KTtcblxuICAgIC8vIERldGVjdCBzY3JvbGxpbmcuXG4gICAgZWZmZWN0KG9uQ2xlYW51cCA9PiB7XG4gICAgICBjb25zdCB2aWV3cG9ydCA9IHRoaXMuX3ZpZXdwb3J0Q29tcG9uZW50KCkudmlld3BvcnRFbGVtZW50O1xuICAgICAgdW50cmFja2VkKCgpID0+IHtcbiAgICAgICAgY29uc3Qgc3Vic2NyaXB0aW9uID0gZnJvbUV2ZW50KHZpZXdwb3J0LCAnc2Nyb2xsJylcbiAgICAgICAgICAucGlwZShzdWJzY3JpYmVJbihmbiA9PiB6b25lLnJ1bk91dHNpZGVBbmd1bGFyKGZuKSkpXG4gICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB0aGlzLl92aWV3cG9ydENoYW5nZSQubmV4dCgpKTtcbiAgICAgICAgb25DbGVhbnVwKCgpID0+IHN1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG5cbiAgLyoqXG4gICAqIFRyYWNrcyB0aGUgdGFiYmFyIGluZGVudHMuXG4gICAqL1xuICBwcml2YXRlIGluc3RhbGxUYWJiYXJJbmRlbnRTaXplVHJhY2tlcigpOiB2b2lkIHtcbiAgICBjb25zdCB0YWJDb3JuZXJSYWRpdXNEaW1lbnNpb24gPSBkaW1lbnNpb24odGhpcy5fdGFiQ29ybmVyUmFkaXVzRWxlbWVudCk7XG4gICAgY29uc3QgcGFkZGluZ0lubGluZURpbWVuc2lvbiA9IGRpbWVuc2lvbih0aGlzLl9wYWRkaW5nSW5saW5lRWxlbWVudCk7XG5cbiAgICBlZmZlY3QoKCkgPT4ge1xuICAgICAgY29uc3QgaW5kZW50ID0gdGFiQ29ybmVyUmFkaXVzRGltZW5zaW9uKCkuY2xpZW50V2lkdGggKyBwYWRkaW5nSW5saW5lRGltZW5zaW9uKCkuY2xpZW50V2lkdGg7XG4gICAgICB0aGlzLl90YWJiYXJJbmRlbnQgPSB7bGVmdDogaW5kZW50LCByaWdodDogaW5kZW50fTtcbiAgICAgIHNldENzc1ZhcmlhYmxlKHRoaXMuX2hvc3QsIHtcbiAgICAgICAgJy0tybVwYXJ0LWJhci1pbmRlbnQtbGVmdCc6IGAke3RoaXMuX3RhYmJhckluZGVudC5sZWZ0fXB4YCxcbiAgICAgICAgJy0tybVwYXJ0LWJhci1pbmRlbnQtcmlnaHQnOiBgJHt0aGlzLl90YWJiYXJJbmRlbnQucmlnaHR9cHhgLFxuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cblxuICBwdWJsaWMgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy51bnNldERyYWdTdGF0ZSgpO1xuICB9XG59XG5cbi8qKlxuICogQ29udGFpbnMgdGhlIGV2ZW50IHBsdXMgZHJhZyBhbmQgc2Nyb2xsIGRpc3RhbmNlLlxuICovXG5pbnRlcmZhY2UgRHJhZ0V2ZW50UGx1c0Rpc3RhbmNlIHtcbiAgLyoqXG4gICAqIFJlZmVyZW5jZSB0byB0aGUgZHJhZyBldmVudC5cbiAgICovXG4gIGV2ZW50OiBEcmFnRXZlbnQ7XG4gIC8qKlxuICAgKiBEaXN0YW5jZSB0aGUgZHJhZyBwb2ludGVyIGhhcyBtb3ZlZCBzaW5jZSB0aGUgbGFzdCBkcmFnIGV2ZW50LlxuICAgKi9cbiAgZHJhZ0Rpc3RhbmNlOiBudW1iZXI7XG4gIC8qKlxuICAgKiBEaXN0YW5jZSB0aGUgdmlld3BvcnQgaGFzIHNjcm9sbGVkIHNpbmNlIHRoZSBsYXN0IGRyYWcgZXZlbnQuXG4gICAqL1xuICBzY3JvbGxEaXN0YW5jZTogbnVtYmVyO1xufVxuIiwiPHNjaS12aWV3cG9ydCBjbGFzcz1cInRhYmJhciBlMmUtdGFiYmFyXCIgc2Nyb2xsYmFyU3R5bGU9XCJoaWRkZW5cIj5cbiAgQGZvciAodmlld0lkIG9mIHBhcnQudmlld0lkcygpOyB0cmFjayB2aWV3SWQpIHtcbiAgICBAaWYgKHZpZXd0YWIgPT09IGRyb3BUYXJnZXRWaWV3VGFiKCkpIHtcbiAgICAgIDxkaXYgY2xhc3M9XCJkaXZpZGVyXCI+PC9kaXY+XG4gICAgfVxuICAgIDx3Yi12aWV3LXRhYiAjdmlld3RhYlxuICAgICAgICAgICAgICAgICBbdmlld0lkXT1cInZpZXdJZFwiXG4gICAgICAgICAgICAgICAgIFtjbGFzcy5kcmFnLXNvdXJjZV09XCJ2aWV3dGFiID09PSBkcmFnU291cmNlVmlld1RhYigpXCJcbiAgICAgICAgICAgICAgICAgW2NsYXNzLmRyb3AtdGFyZ2V0XT1cInZpZXd0YWIgPT09IGRyb3BUYXJnZXRWaWV3VGFiKClcIi8+XG4gICAgPGRpdiBjbGFzcz1cImRpdmlkZXJcIj48L2Rpdj5cbiAgfVxuXG4gIDwhLS0gUGxhY2Vob2xkZXIgZm9yIGV4cGFuZGluZyB0aGUgdmlld3BvcnQgd2hlbiBkcmFnZ2luZyBhIHRhYiB0byB0aGUgcmlnaHQsIG1vdmluZyBwYXJ0IGFjdGlvbnMgYWxvbmcgd2l0aCB0aGUgZHJhZ292ZXIgZXZlbnQuIC0tPlxuICA8ZGl2IGNsYXNzPVwiZHJhZy1wbGFjZWhvbGRlclwiPjwvZGl2PlxuPC9zY2ktdmlld3BvcnQ+XG5cbjwhLS0gQWN0aW9ucyAtLT5cbkBpZiAoc3RhcnRBY3Rpb25zKCkubGVuZ3RoKSB7XG4gIDx3Yi1wYXJ0LWFjdGlvbi1iYXIgW2FjdGlvbnNdPVwic3RhcnRBY3Rpb25zKClcIiBjbGFzcz1cInN0YXJ0XCIvPlxufVxuPGRpdiBjbGFzcz1cImZpbGxlclwiICNmaWxsZXI+PC9kaXY+XG5AaWYgKGVuZEFjdGlvbnMoKS5sZW5ndGgpIHtcbiAgPHdiLXBhcnQtYWN0aW9uLWJhciBbYWN0aW9uc109XCJlbmRBY3Rpb25zKClcIiBjbGFzcz1cImVuZFwiLz5cbn1cblxuPCEtLSBWaWV3IExpc3QgRHJvcGRvd24gLS0+XG48d2Itdmlldy1saXN0LWJ1dHRvbi8+XG5cbjwhLS0gRWxlbWVudCBmb3IgaW5qZWN0aW5nIHRoZSBjb3JuZXIgcmFkaXVzIGludG8gdGhlIGNvbXBvbmVudC4gLS0+XG48ZGl2IGNsYXNzPVwidGFiLWNvcm5lci1yYWRpdXNcIiAjdGFiX2Nvcm5lcl9yYWRpdXM+PC9kaXY+XG48IS0tIEVsZW1lbnQgZm9yIGluamVjdGluZyB0aGUgdGFiYmFyIHBhZGRpbmcgaW50byB0aGUgY29tcG9uZW50LiAtLT5cbjxkaXYgY2xhc3M9XCJwYWRkaW5nLWlubGluZVwiICNwYWRkaW5nX2lubGluZT48L2Rpdj5cbiJdfQ==