@banta/sdk 4.9.1 → 5.0.0

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 (140) hide show
  1. package/{esm2020 → esm2022}/banta-sdk.mjs +4 -4
  2. package/{esm2020 → esm2022}/lib/attachment-scraper.mjs +1 -1
  3. package/esm2022/lib/banta/banta.component.mjs +204 -0
  4. package/{esm2020 → esm2022}/lib/banta-logo.component.mjs +11 -11
  5. package/esm2022/lib/banta-sdk.module.mjs +143 -0
  6. package/esm2022/lib/chat/banta-chat/banta-chat.component.mjs +187 -0
  7. package/esm2022/lib/chat/chat-message/chat-message.component.mjs +62 -0
  8. package/esm2022/lib/chat/chat-view/chat-view.component.mjs +170 -0
  9. package/{esm2020 → esm2022}/lib/chat/chat.module.mjs +51 -51
  10. package/{esm2020 → esm2022}/lib/chat/index.mjs +5 -5
  11. package/esm2022/lib/chat/live-chat-message.component.mjs +80 -0
  12. package/{esm2020 → esm2022}/lib/chat-backend-base.mjs +30 -30
  13. package/esm2022/lib/chat-backend.mjs +163 -0
  14. package/{esm2020 → esm2022}/lib/chat-source-base.mjs +1 -1
  15. package/esm2022/lib/chat-source.mjs +233 -0
  16. package/esm2022/lib/comments/attachment-button/attachment-button.component.mjs +76 -0
  17. package/esm2022/lib/comments/attachment-scraper.directive.mjs +107 -0
  18. package/esm2022/lib/comments/banta-comments/banta-comments.component.mjs +739 -0
  19. package/esm2022/lib/comments/comment/comment.component.mjs +175 -0
  20. package/esm2022/lib/comments/comment-field/comment-field.component.mjs +401 -0
  21. package/esm2022/lib/comments/comment-sort/comment-sort.component.mjs +37 -0
  22. package/esm2022/lib/comments/comment-view/comment-view.component.mjs +470 -0
  23. package/esm2022/lib/comments/comments.module.mjs +111 -0
  24. package/{esm2020 → esm2022}/lib/comments/index.mjs +10 -10
  25. package/esm2022/lib/comments/live-comment.component.mjs +80 -0
  26. package/{esm2020 → esm2022}/lib/comments/reply-send-options.directive.mjs +13 -13
  27. package/esm2022/lib/common/attachment/attachment.component.mjs +112 -0
  28. package/{esm2020 → esm2022}/lib/common/attachments/attachments.component.mjs +75 -75
  29. package/{esm2020 → esm2022}/lib/common/common.module.mjs +68 -68
  30. package/{esm2020 → esm2022}/lib/common/index.mjs +10 -10
  31. package/{esm2020 → esm2022}/lib/common/lazy-connection.mjs +14 -14
  32. package/esm2022/lib/common/lightbox/lightbox.component.mjs +31 -0
  33. package/esm2022/lib/common/markdown-to-html.pipe.mjs +89 -0
  34. package/esm2022/lib/common/mention-linker.pipe.mjs +35 -0
  35. package/esm2022/lib/common/timer-pool.service.mjs +83 -0
  36. package/esm2022/lib/common/timestamp.component.mjs +123 -0
  37. package/{esm2020 → esm2022}/lib/common/trust-resource-url.pipe.mjs +22 -22
  38. package/esm2022/lib/emoji/emoji-selector-button.component.mjs +115 -0
  39. package/esm2022/lib/emoji/emoji-selector-panel/emoji-selector-panel.component.mjs +98 -0
  40. package/{esm2020 → esm2022}/lib/emoji/emoji.module.mjs +55 -55
  41. package/{esm2020 → esm2022}/lib/emoji/emojis.mjs +6507 -6507
  42. package/{esm2020 → esm2022}/lib/emoji/index.mjs +4 -4
  43. package/esm2022/lib/giphy-attachments.mjs +16 -0
  44. package/{esm2020 → esm2022}/lib/index.mjs +19 -19
  45. package/{esm2020 → esm2022}/lib/live-message.component.mjs +61 -61
  46. package/{esm2020 → esm2022}/lib/message-menu-item.mjs +1 -1
  47. package/{esm2020 → esm2022}/lib/sdk-options.mjs +1 -1
  48. package/esm2022/lib/static-chat-source.mjs +71 -0
  49. package/esm2022/lib/tweet-attachments.mjs +13 -0
  50. package/esm2022/lib/url-attachments.mjs +42 -0
  51. package/esm2022/lib/youtube-attachments.mjs +29 -0
  52. package/{esm2020 → esm2022}/public-api.mjs +4 -4
  53. package/{fesm2020 → fesm2022}/banta-sdk.mjs +10753 -10754
  54. package/fesm2022/banta-sdk.mjs.map +1 -0
  55. package/index.d.ts +5 -5
  56. package/lib/attachment-scraper.d.ts +15 -15
  57. package/lib/banta/banta.component.d.ts +58 -58
  58. package/lib/banta-logo.component.d.ts +5 -5
  59. package/lib/banta-sdk.module.d.ts +31 -31
  60. package/lib/chat/banta-chat/banta-chat.component.d.ts +70 -70
  61. package/lib/chat/chat-message/chat-message.component.d.ts +21 -21
  62. package/lib/chat/chat-view/chat-view.component.d.ts +52 -52
  63. package/lib/chat/chat.module.d.ts +15 -15
  64. package/lib/chat/index.d.ts +5 -5
  65. package/lib/chat/live-chat-message.component.d.ts +23 -23
  66. package/lib/chat-backend-base.d.ts +36 -36
  67. package/lib/chat-backend.d.ts +55 -55
  68. package/lib/chat-source-base.d.ts +44 -44
  69. package/lib/chat-source.d.ts +65 -65
  70. package/lib/comments/attachment-button/attachment-button.component.d.ts +17 -17
  71. package/lib/comments/attachment-scraper.directive.d.ts +21 -21
  72. package/lib/comments/banta-comments/banta-comments.component.d.ts +196 -196
  73. package/lib/comments/comment/comment.component.d.ts +72 -72
  74. package/lib/comments/comment-field/comment-field.component.d.ts +89 -89
  75. package/lib/comments/comment-sort/comment-sort.component.d.ts +12 -12
  76. package/lib/comments/comment-view/comment-view.component.d.ts +121 -121
  77. package/lib/comments/comments.module.d.ts +30 -30
  78. package/lib/comments/index.d.ts +10 -10
  79. package/lib/comments/live-comment.component.d.ts +23 -23
  80. package/lib/comments/reply-send-options.directive.d.ts +5 -5
  81. package/lib/common/attachment/attachment.component.d.ts +33 -33
  82. package/lib/common/attachments/attachments.component.d.ts +26 -26
  83. package/lib/common/common.module.d.ts +19 -19
  84. package/lib/common/index.d.ts +10 -10
  85. package/lib/common/lazy-connection.d.ts +6 -6
  86. package/lib/common/lightbox/lightbox.component.d.ts +14 -14
  87. package/lib/common/markdown-to-html.pipe.d.ts +15 -15
  88. package/lib/common/mention-linker.pipe.d.ts +13 -13
  89. package/lib/common/timer-pool.service.d.ts +15 -15
  90. package/lib/common/timestamp.component.d.ts +19 -19
  91. package/lib/common/trust-resource-url.pipe.d.ts +10 -10
  92. package/lib/emoji/emoji-selector-button.component.d.ts +30 -30
  93. package/lib/emoji/emoji-selector-panel/emoji-selector-panel.component.d.ts +26 -26
  94. package/lib/emoji/emoji.module.d.ts +16 -16
  95. package/lib/emoji/emojis.d.ts +6507 -6507
  96. package/lib/emoji/index.d.ts +4 -4
  97. package/lib/giphy-attachments.d.ts +5 -5
  98. package/lib/index.d.ts +19 -19
  99. package/lib/live-message.component.d.ts +22 -22
  100. package/lib/message-menu-item.d.ts +6 -6
  101. package/lib/sdk-options.d.ts +5 -5
  102. package/lib/static-chat-source.d.ts +42 -42
  103. package/lib/tweet-attachments.d.ts +5 -5
  104. package/lib/url-attachments.d.ts +14 -14
  105. package/lib/youtube-attachments.d.ts +5 -5
  106. package/package.json +14 -20
  107. package/public-api.d.ts +1 -1
  108. package/esm2020/lib/banta/banta.component.mjs +0 -204
  109. package/esm2020/lib/banta-sdk.module.mjs +0 -143
  110. package/esm2020/lib/chat/banta-chat/banta-chat.component.mjs +0 -187
  111. package/esm2020/lib/chat/chat-message/chat-message.component.mjs +0 -62
  112. package/esm2020/lib/chat/chat-view/chat-view.component.mjs +0 -170
  113. package/esm2020/lib/chat/live-chat-message.component.mjs +0 -80
  114. package/esm2020/lib/chat-backend.mjs +0 -163
  115. package/esm2020/lib/chat-source.mjs +0 -233
  116. package/esm2020/lib/comments/attachment-button/attachment-button.component.mjs +0 -76
  117. package/esm2020/lib/comments/attachment-scraper.directive.mjs +0 -107
  118. package/esm2020/lib/comments/banta-comments/banta-comments.component.mjs +0 -740
  119. package/esm2020/lib/comments/comment/comment.component.mjs +0 -175
  120. package/esm2020/lib/comments/comment-field/comment-field.component.mjs +0 -401
  121. package/esm2020/lib/comments/comment-sort/comment-sort.component.mjs +0 -37
  122. package/esm2020/lib/comments/comment-view/comment-view.component.mjs +0 -470
  123. package/esm2020/lib/comments/comments.module.mjs +0 -111
  124. package/esm2020/lib/comments/live-comment.component.mjs +0 -80
  125. package/esm2020/lib/common/attachment/attachment.component.mjs +0 -112
  126. package/esm2020/lib/common/lightbox/lightbox.component.mjs +0 -31
  127. package/esm2020/lib/common/markdown-to-html.pipe.mjs +0 -89
  128. package/esm2020/lib/common/mention-linker.pipe.mjs +0 -35
  129. package/esm2020/lib/common/timer-pool.service.mjs +0 -83
  130. package/esm2020/lib/common/timestamp.component.mjs +0 -123
  131. package/esm2020/lib/emoji/emoji-selector-button.component.mjs +0 -116
  132. package/esm2020/lib/emoji/emoji-selector-panel/emoji-selector-panel.component.mjs +0 -98
  133. package/esm2020/lib/giphy-attachments.mjs +0 -16
  134. package/esm2020/lib/static-chat-source.mjs +0 -71
  135. package/esm2020/lib/tweet-attachments.mjs +0 -13
  136. package/esm2020/lib/url-attachments.mjs +0 -42
  137. package/esm2020/lib/youtube-attachments.mjs +0 -29
  138. package/fesm2015/banta-sdk.mjs +0 -11181
  139. package/fesm2015/banta-sdk.mjs.map +0 -1
  140. package/fesm2020/banta-sdk.mjs.map +0 -1
@@ -0,0 +1,470 @@
1
+ import { Component, Input, ViewChild, Output, HostBinding, ViewChildren } from "@angular/core";
2
+ import { CommentsOrder, FilterMode } from '@banta/common';
3
+ import { Subject, Subscription } from 'rxjs';
4
+ import { CommentComponent } from "../comment/comment.component";
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "../../chat-backend-base";
7
+ import * as i2 from "@angular/common";
8
+ import * as i3 from "@angular/material/icon";
9
+ import * as i4 from "@angular/material/button";
10
+ import * as i5 from "@angular/material/progress-spinner";
11
+ import * as i6 from "../comment/comment.component";
12
+ export class CommentViewComponent {
13
+ constructor(backend, elementRef) {
14
+ this.backend = backend;
15
+ this.elementRef = elementRef;
16
+ //#endregion
17
+ //#region Fields
18
+ this._sourceSubs = new Subscription();
19
+ this.menuMessage = null;
20
+ this.messages = [];
21
+ this.customSortEnabled = false;
22
+ this.sourceLoaded = new Promise(r => this.markSourceLoaded = r);
23
+ this.isViewingMore = false;
24
+ this.isLoadingMore = false;
25
+ this.hasMore = false;
26
+ this.newMessages = [];
27
+ this.olderMessages = [];
28
+ //#endregion
29
+ //#region Inputs
30
+ this.maxMessages = 2000;
31
+ this.maxVisibleMessages = 200;
32
+ this.newestLast = false;
33
+ this.holdNewMessages = false;
34
+ this.showEmptyState = true;
35
+ this.allowReplies = true;
36
+ this.enableHoldOnClick = false;
37
+ this.enableHoldOnScroll = true;
38
+ this.customMenuItems = [];
39
+ //#endregion
40
+ //#region Outputs
41
+ this._selected = new Subject();
42
+ this._liked = new Subject();
43
+ this._unliked = new Subject();
44
+ this._reported = new Subject();
45
+ this._userSelected = new Subject();
46
+ this._usernameSelected = new Subject();
47
+ this._avatarSelected = new Subject();
48
+ this._shared = new Subject();
49
+ this._deleted = new Subject();
50
+ this._messageEdited = new Subject();
51
+ this._sortOrderChanged = new Subject();
52
+ this._filterModeChanged = new Subject();
53
+ this.userSelected = this._userSelected.asObservable();
54
+ this.reported = this._reported.asObservable();
55
+ this.liked = this._liked.asObservable();
56
+ this.unliked = this._unliked.asObservable();
57
+ this.usernameSelected = this._usernameSelected.asObservable();
58
+ this.avatarSelected = this._avatarSelected.asObservable();
59
+ this.shared = this._shared.asObservable();
60
+ this.deleted = this._deleted.asObservable();
61
+ this.selected = this._selected.asObservable();
62
+ this.messageEdited = this._messageEdited.asObservable();
63
+ this.sortOrderChanged = this._sortOrderChanged.asObservable();
64
+ this.filterModeChanged = this._filterModeChanged.asObservable();
65
+ }
66
+ get source() { return this._source; }
67
+ set source(value) { this.setSource(value); }
68
+ get comments() { return Array.from(this.commentsQuery); }
69
+ //#endregion
70
+ /**
71
+ * Returns true if this message can be found within one of the message buffers (older, current, newer)
72
+ * @param message
73
+ */
74
+ isMessageLoadedInContext(message) {
75
+ return this.olderMessages.find(x => x.id === message.id)
76
+ || this.messages.find(x => x.id === message.id)
77
+ || this.newMessages.find(x => x.id === message.id);
78
+ }
79
+ async loadMessageInContext(message) {
80
+ await this.sourceLoaded;
81
+ console.log(`Loading message ${message.id} in context...`);
82
+ while (this.hasMore && !this.isMessageLoadedInContext(message)) {
83
+ console.log(`...Need to load more comments to find ${message.id}`);
84
+ await this.showMore();
85
+ }
86
+ if (!this.isMessageLoadedInContext(message)) {
87
+ console.error(`Error while loading message in context: Failed to find message ${message.id}, maybe it was deleted!`);
88
+ return false;
89
+ }
90
+ let pageSize = this.maxVisibleMessages;
91
+ let items = [].concat(this.olderMessages, this.messages, this.newMessages);
92
+ let index = items.findIndex(x => x.id === message.id);
93
+ if (index < 0) {
94
+ console.error(`Error while loading message in context: Message was not present in message list!`);
95
+ return false;
96
+ }
97
+ let startIndex = Math.max(0, index - pageSize / 2);
98
+ this.newMessages = items.splice(0, startIndex);
99
+ this.messages = items.splice(0, pageSize);
100
+ this.olderMessages = items;
101
+ this.isViewingMore = true;
102
+ }
103
+ get shouldShowNewMessageIndicator() {
104
+ return this.isViewingMore
105
+ || this.customSortEnabled
106
+ || this.source.filterMode !== FilterMode.ALL
107
+ || this.newMessages.length > 0;
108
+ }
109
+ get shouldHoldNewMessages() {
110
+ if (this.holdNewMessages || this.isViewingMore) {
111
+ console.log(`holding due to settings`);
112
+ return true;
113
+ }
114
+ if (this.enableHoldOnScroll) {
115
+ let keyMessage;
116
+ if (this.newestLast)
117
+ keyMessage = this.messages[this.messages.length - 1];
118
+ else
119
+ keyMessage = this.messages[0];
120
+ if (keyMessage) {
121
+ const messageElement = this.getElementForComment(keyMessage.id);
122
+ if (messageElement) {
123
+ if (!this.isElementVisible(messageElement)) {
124
+ console.log(`key element is not visible`);
125
+ return true;
126
+ }
127
+ else {
128
+ console.log(`key element is visible`);
129
+ }
130
+ }
131
+ else {
132
+ console.log(`could not find key element`);
133
+ }
134
+ }
135
+ else {
136
+ console.log(`could not find key message`);
137
+ }
138
+ return false;
139
+ }
140
+ return false;
141
+ }
142
+ isElementVisible(element) {
143
+ const elementRect = element.getBoundingClientRect();
144
+ return !!elementRect
145
+ && elementRect.bottom >= 0
146
+ && elementRect.right >= 0
147
+ && elementRect.left <= document.documentElement.clientWidth
148
+ && elementRect.top <= document.documentElement.clientHeight;
149
+ }
150
+ /**
151
+ * Get the CommentComponent instantiated for the given ChatMessage,
152
+ * if it exists in the current view. Note that messages which are not
153
+ * currently shown to the user will not return a CommentComponent.
154
+ * @param message
155
+ * @returns
156
+ */
157
+ getCommentComponentForMessage(message) {
158
+ if (!message)
159
+ throw new Error(`You must pass a valid ChatMessage`);
160
+ return this.comments.find(x => x.message?.id === message.id);
161
+ }
162
+ saveEdit(message, newMessage) {
163
+ this._messageEdited.next({ message, newMessage });
164
+ }
165
+ likeMessage(message) {
166
+ this._liked.next(message);
167
+ }
168
+ unlikeMessage(message) {
169
+ this._unliked.next(message);
170
+ }
171
+ reportMessage(message) {
172
+ this._reported.next(message);
173
+ }
174
+ selectMessage(message) {
175
+ this._selected.next(message);
176
+ }
177
+ selectMessageUser(message) {
178
+ this._userSelected.next(message);
179
+ }
180
+ selectUsername(user) {
181
+ this._usernameSelected.next(user);
182
+ }
183
+ selectAvatar(user) {
184
+ this._avatarSelected.next(user);
185
+ }
186
+ sharedMessage(message) {
187
+ this._shared.next(message);
188
+ }
189
+ startEditing(message) {
190
+ this.messages.forEach(m => m.transientState.editing = false);
191
+ message.transientState.editing = true;
192
+ }
193
+ deleteMessage(message) {
194
+ this._deleted.next(message);
195
+ }
196
+ setSource(value) {
197
+ this.customSortEnabled = value?.sortOrder !== CommentsOrder.NEWEST;
198
+ this.newMessages = [];
199
+ this.olderMessages = [];
200
+ window.bantaSourceDebug = value;
201
+ if (this._sourceSubs) {
202
+ this._sourceSubs.unsubscribe();
203
+ this._sourceSubs = null;
204
+ }
205
+ this._source = value;
206
+ if (value) {
207
+ const messages = (value.messages || []).slice();
208
+ this.messages = messages;
209
+ this.olderMessages = messages.splice(this.maxVisibleMessages, messages.length);
210
+ this.hasMore = true; //this.olderMessages.length > 0;
211
+ this._sourceSubs = new Subscription();
212
+ this._sourceSubs.add(this._source.messageReceived.subscribe(msg => this.messageReceived(msg)));
213
+ this._sourceSubs.add(this._source.messageSent.subscribe(msg => this.messageSent(msg)));
214
+ this._sourceSubs.add(this.backend.userChanged.subscribe(user => this.currentUser = user));
215
+ this.getInitialMessages();
216
+ }
217
+ }
218
+ async getInitialMessages() {
219
+ let messages = (await this._source.getExistingMessages());
220
+ messages.forEach(m => m.transientState ??= {});
221
+ this.messages = this.newestLast ? messages.slice().reverse() : messages;
222
+ this.sortMessages();
223
+ if (this.markSourceLoaded)
224
+ this.markSourceLoaded();
225
+ }
226
+ messageIdentity(index, chatMessage) {
227
+ return chatMessage.id;
228
+ }
229
+ async showNew(event) {
230
+ let naturalOrder = CommentsOrder.NEWEST;
231
+ if (this.source && (this.source.sortOrder !== naturalOrder || this.source.filterMode !== FilterMode.ALL)) {
232
+ if (this.source.sortOrder !== naturalOrder)
233
+ this._sortOrderChanged.next(naturalOrder);
234
+ if (this.source.filterMode !== FilterMode.ALL)
235
+ this._filterModeChanged.next(FilterMode.ALL);
236
+ return;
237
+ }
238
+ this.isViewingMore = false;
239
+ if (this.newestLast)
240
+ this.messages = this.messages.concat(this.newMessages.splice(0, this.newMessages.length));
241
+ else
242
+ this.messages = this.newMessages.splice(0, this.newMessages.length).concat(this.messages);
243
+ let overflow = this.messages.splice(this.maxVisibleMessages, this.messages.length);
244
+ this.olderMessages = overflow.concat(this.olderMessages);
245
+ this.olderMessages.splice(this.maxMessages - this.maxVisibleMessages, this.olderMessages.length);
246
+ this.hasMore = this.olderMessages.length > 0;
247
+ if (this.messages.length > 0) {
248
+ if (this.newestLast) {
249
+ this.scrollToComment(this.messages[this.messages.length - 1].id);
250
+ }
251
+ else {
252
+ this.scrollToComment(this.messages[0].id);
253
+ }
254
+ }
255
+ }
256
+ async showMore() {
257
+ this.isViewingMore = true;
258
+ if (this.olderMessages.length > 0) {
259
+ this.isLoadingMore = false;
260
+ this.messages = this.messages.concat(this.olderMessages.splice(0, 50));
261
+ }
262
+ this.isLoadingMore = true;
263
+ let nextPageSize = 20;
264
+ let lastMessage;
265
+ if (this.newestLast) {
266
+ lastMessage = this.olderMessages[0] ?? this.messages[0];
267
+ }
268
+ else {
269
+ lastMessage = this.olderMessages[this.olderMessages.length - 1] ?? this.messages[this.messages.length - 1];
270
+ }
271
+ if (!lastMessage) {
272
+ this.isLoadingMore = false;
273
+ this.hasMore = false;
274
+ return;
275
+ }
276
+ let messages = await this.source.loadAfter(lastMessage, nextPageSize);
277
+ if (this.newestLast)
278
+ messages = messages.slice().reverse();
279
+ messages.forEach(m => m.transientState ??= {});
280
+ if (this.newestLast)
281
+ this.messages = messages.concat(this.messages);
282
+ else
283
+ this.messages = this.messages.concat(messages);
284
+ this.isLoadingMore = false;
285
+ if (messages.length === 0) {
286
+ console.log(`Reached the end of the list.`);
287
+ this.hasMore = false;
288
+ }
289
+ }
290
+ addMessage(message) {
291
+ if (!message.transientState)
292
+ message.transientState ??= {};
293
+ let destination = this.messages;
294
+ let bucket = this.olderMessages;
295
+ let newestLast = this.newestLast;
296
+ if (this.shouldHoldNewMessages) {
297
+ destination = this.newMessages;
298
+ bucket = null;
299
+ }
300
+ if (newestLast) {
301
+ destination.push(message);
302
+ let overflow = destination.splice(this.maxVisibleMessages, destination.length);
303
+ bucket?.push(...overflow);
304
+ }
305
+ else {
306
+ destination.unshift(message);
307
+ let overflow = destination.splice(this.maxVisibleMessages, destination.length);
308
+ bucket?.unshift(...overflow);
309
+ }
310
+ if (bucket?.length > 0)
311
+ this.hasMore = true;
312
+ message.pagingCursor = String(this.incrementPagingCursors());
313
+ this.sortMessages();
314
+ }
315
+ incrementPagingCursors() {
316
+ if (this.source.sortOrder !== CommentsOrder.NEWEST)
317
+ return;
318
+ let maxPagingCursor = 0;
319
+ for (let group of [this.messages, this.olderMessages, this.newMessages]) {
320
+ for (let message of group) {
321
+ if (message.pagingCursor) {
322
+ let pagingCursor = Number(message.pagingCursor) + 1;
323
+ if (pagingCursor > maxPagingCursor)
324
+ maxPagingCursor = pagingCursor;
325
+ message.pagingCursor = String(pagingCursor);
326
+ }
327
+ }
328
+ }
329
+ return maxPagingCursor;
330
+ }
331
+ /**
332
+ * Wait for all currently visible comments to be fully loaded, including all attachments.
333
+ * Doing this will prevent layout shift when scrolling to a specific comment.
334
+ */
335
+ async waitForAllCommentsToLoad() {
336
+ await new Promise(r => setTimeout(r, 100));
337
+ await this.sourceLoaded;
338
+ await Promise.all(this.comments.map(x => x.waitForLoad()));
339
+ }
340
+ sortMessages() {
341
+ if (!this.source)
342
+ return;
343
+ let sorter;
344
+ if (this.source.sortOrder === CommentsOrder.LIKES)
345
+ sorter = (a, b) => b.likes - a.likes;
346
+ else if (this.source.sortOrder === CommentsOrder.NEWEST)
347
+ sorter = (a, b) => (b.sentAt - a.sentAt) * (this.newestLast ? -1 : 1);
348
+ else if (this.source.sortOrder === CommentsOrder.OLDEST)
349
+ sorter = (a, b) => (a.sentAt - b.sentAt) * (this.newestLast ? -1 : 1);
350
+ this.messages.sort(sorter);
351
+ this.olderMessages.sort(sorter);
352
+ this.newMessages.sort(sorter);
353
+ }
354
+ messageReceived(message) {
355
+ this.addMessage(message);
356
+ }
357
+ isScrolledToLatest() {
358
+ if (!this.messageContainer)
359
+ return false;
360
+ const el = this.messageContainer.nativeElement;
361
+ const currentScroll = el.scrollTop;
362
+ const currentTotal = el.scrollHeight - el.offsetHeight;
363
+ return currentScroll > currentTotal - 10;
364
+ }
365
+ messageSent(message) {
366
+ this.addMessage(message);
367
+ if (!this.messageContainer)
368
+ return;
369
+ this.scrollToLatest();
370
+ }
371
+ scrollToLatest() {
372
+ if (!this.messageContainer) {
373
+ return;
374
+ }
375
+ const el = this.messageContainer.nativeElement;
376
+ el.scrollIntoView({ block: 'start' });
377
+ //el.scrollTop = el.scrollHeight;
378
+ }
379
+ get element() {
380
+ return this.elementRef.nativeElement;
381
+ }
382
+ async scrollToComment(commentId) {
383
+ if (typeof window === 'undefined')
384
+ return;
385
+ await this.waitForAllCommentsToLoad();
386
+ const comment = this.getElementForComment(commentId);
387
+ if (comment) {
388
+ comment.scrollIntoView({
389
+ inline: 'center',
390
+ block: 'center'
391
+ });
392
+ }
393
+ }
394
+ getElementForComment(commentId) {
395
+ return this.element.querySelector(`[data-comment-id="${commentId}"]`);
396
+ }
397
+ mentionsMe(message) {
398
+ if (!this.currentUser)
399
+ return false;
400
+ if (message.message.includes(`@${this.currentUser.username}`))
401
+ return true;
402
+ return false;
403
+ }
404
+ static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "17.3.8", ngImport: i0, type: CommentViewComponent, deps: [{ token: i1.ChatBackendBase }, { token: i0.ElementRef }], target: i0.ɵɵFactoryTarget.Component }); }
405
+ static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "17.3.8", type: CommentViewComponent, selector: "banta-comment-view", inputs: { source: "source", maxMessages: "maxMessages", maxVisibleMessages: "maxVisibleMessages", newestLast: "newestLast", holdNewMessages: "holdNewMessages", showEmptyState: "showEmptyState", allowReplies: "allowReplies", enableHoldOnClick: "enableHoldOnClick", enableHoldOnScroll: "enableHoldOnScroll", customMenuItems: "customMenuItems", fixedHeight: "fixedHeight", selectedMessage: "selectedMessage", genericAvatarUrl: "genericAvatarUrl" }, outputs: { userSelected: "userSelected", reported: "reported", liked: "liked", unliked: "unliked", usernameSelected: "usernameSelected", avatarSelected: "avatarSelected", shared: "shared", deleted: "deleted", selected: "selected", messageEdited: "messageEdited", sortOrderChanged: "sortOrderChanged", filterModeChanged: "filterModeChanged" }, host: { properties: { "class.fixed-height": "this.fixedHeight" } }, viewQueries: [{ propertyName: "messageContainer", first: true, predicate: ["messageContainer"], descendants: true }, { propertyName: "commentsQuery", predicate: CommentComponent, descendants: true }], ngImport: i0, template: "<div class=\"message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"top-sticky\">\r\n <a *ngIf=\"!newestLast\" mat-button class=\"nav\" [class.visible]=\"shouldShowNewMessageIndicator\" href=\"javascript:;\" (click)=\"showNew($event)\">\r\n <mat-icon>file_upload</mat-icon>\r\n <ng-container *ngIf=\"newMessages.length >= 1\">\r\n New ({{newMessages.length}})\r\n </ng-container>\r\n <ng-container *ngIf=\"newMessages.length == 0\">\r\n Newest\r\n </ng-container>\r\n </a>\r\n </div>\r\n <a mat-button class=\"nav\" [class.visible]=\"newestLast && hasMore && !isLoadingMore\" href=\"javascript:;\" (click)=\"showMore()\">Show earlier</a>\r\n\r\n <ng-container *ngIf=\"messages.length === 0\">\r\n <div class=\"empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let message of messages; trackBy: messageIdentity\">\r\n <banta-comment\r\n *ngIf=\"!message.hidden\"\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"enableHoldOnClick ? (holdNewMessages = true) : undefined\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n ></banta-comment>\r\n <div class=\"inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n </ng-container>\r\n\r\n <div class=\"nav-point bottom-sticky\">\r\n <a *ngIf=\"newestLast\" mat-button class=\"nav\" [class.visible]=\"shouldShowNewMessageIndicator\" href=\"javascript:;\" (click)=\"showNew($event)\">\r\n <mat-icon>file_download</mat-icon>\r\n <ng-container *ngIf=\"newMessages.length >= 1\">\r\n New ({{newMessages.length}})\r\n </ng-container>\r\n <ng-container *ngIf=\"newMessages.length == 0\">\r\n Newest\r\n </ng-container>\r\n </a>\r\n </div>\r\n <a mat-button class=\"nav\" [class.visible]=\"!newestLast && hasMore && !isLoadingMore\" href=\"javascript:;\" (click)=\"showMore()\">Show more</a>\r\n\r\n <div class=\"loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <!-- <div style=\"color: #666\">\r\n n={{newMessages.length}}, m={{messages.length}}, o={{olderMessages.length}},\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div> -->\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.message-container.no-scroll{height:auto;overflow-y:visible}.message-container.faded{opacity:.25}.message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .message-container{overflow-y:auto}:host-context(.mat-dark-theme) .message-container{color:#fff;background:#111}.empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}a.nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background:#222}a.nav.visible{opacity:1;pointer-events:initial}.top-sticky{position:sticky;top:.5em;z-index:10}.bottom-sticky{position:sticky;bottom:3em;z-index:10}.loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.message-container{padding:0 0 3em}}\n"], dependencies: [{ kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i3.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i4.MatAnchor, selector: "a[mat-button], a[mat-raised-button], a[mat-flat-button], a[mat-stroked-button]", exportAs: ["matButton", "matAnchor"] }, { kind: "component", type: i5.MatProgressSpinner, selector: "mat-progress-spinner, mat-spinner", inputs: ["color", "mode", "value", "diameter", "strokeWidth"], exportAs: ["matProgressSpinner"] }, { kind: "component", type: i6.CommentComponent, selector: "banta-comment", inputs: ["message", "customMenuItems", "showReplyAction", "maxLength", "permissions", "mine", "editing", "genericAvatarUrl", "readonly"], outputs: ["liked", "unliked", "selected", "edited", "deleted", "editStarted", "editEnded", "shared", "userSelected", "usernameSelected", "avatarSelected", "reported", "loaded"] }] }); }
406
+ }
407
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "17.3.8", ngImport: i0, type: CommentViewComponent, decorators: [{
408
+ type: Component,
409
+ args: [{ selector: 'banta-comment-view', template: "<div class=\"message-container\" #messageContainer>\r\n <ng-content select=\"[data-before]\"></ng-content>\r\n\r\n <div class=\"top-sticky\">\r\n <a *ngIf=\"!newestLast\" mat-button class=\"nav\" [class.visible]=\"shouldShowNewMessageIndicator\" href=\"javascript:;\" (click)=\"showNew($event)\">\r\n <mat-icon>file_upload</mat-icon>\r\n <ng-container *ngIf=\"newMessages.length >= 1\">\r\n New ({{newMessages.length}})\r\n </ng-container>\r\n <ng-container *ngIf=\"newMessages.length == 0\">\r\n Newest\r\n </ng-container>\r\n </a>\r\n </div>\r\n <a mat-button class=\"nav\" [class.visible]=\"newestLast && hasMore && !isLoadingMore\" href=\"javascript:;\" (click)=\"showMore()\">Show earlier</a>\r\n\r\n <ng-container *ngIf=\"messages.length === 0\">\r\n <div class=\"empty-state\" *ngIf=\"showEmptyState\">\r\n Be the first to comment!\r\n </div>\r\n </ng-container>\r\n <ng-container *ngFor=\"let message of messages; trackBy: messageIdentity\">\r\n <banta-comment\r\n *ngIf=\"!message.hidden\"\r\n class=\"abbreviated\"\r\n \r\n [customMenuItems]=\"customMenuItems\"\r\n [message]=\"message\"\r\n [mine]=\"currentUser?.id === message.user?.id\"\r\n [permissions]=\"source?.permissions\"\r\n [showReplyAction]=\"allowReplies\"\r\n [editing]=\"message.transientState.editing\"\r\n [genericAvatarUrl]=\"genericAvatarUrl\"\r\n [readonly]=\"source?.readonly\"\r\n (click)=\"enableHoldOnClick ? (holdNewMessages = true) : undefined\"\r\n (editStarted)=\"startEditing(message)\"\r\n (deleted)=\"deleteMessage(message)\"\r\n (editEnded)=\"message.transientState.editing = false\"\r\n (edited)=\"saveEdit(message, $event)\"\r\n (userSelected)=\"selectMessageUser(message)\"\r\n (avatarSelected)=\"selectAvatar($event)\"\r\n (usernameSelected)=\"selectUsername($event)\"\r\n (liked)=\"likeMessage(message)\"\r\n (unliked)=\"unlikeMessage(message)\"\r\n (reported)=\"reportMessage(message)\"\r\n (selected)=\"selectMessage(message)\"\r\n (shared)=\"sharedMessage($event)\"\r\n ></banta-comment>\r\n <div class=\"inline-replies-container\" *ngIf=\"selectedMessage === message\">\r\n <ng-content select=\".inline-replies\"></ng-content>\r\n </div>\r\n </ng-container>\r\n\r\n <div class=\"nav-point bottom-sticky\">\r\n <a *ngIf=\"newestLast\" mat-button class=\"nav\" [class.visible]=\"shouldShowNewMessageIndicator\" href=\"javascript:;\" (click)=\"showNew($event)\">\r\n <mat-icon>file_download</mat-icon>\r\n <ng-container *ngIf=\"newMessages.length >= 1\">\r\n New ({{newMessages.length}})\r\n </ng-container>\r\n <ng-container *ngIf=\"newMessages.length == 0\">\r\n Newest\r\n </ng-container>\r\n </a>\r\n </div>\r\n <a mat-button class=\"nav\" [class.visible]=\"!newestLast && hasMore && !isLoadingMore\" href=\"javascript:;\" (click)=\"showMore()\">Show more</a>\r\n\r\n <div class=\"loading-more\" *ngIf=\"isLoadingMore\">\r\n <mat-spinner></mat-spinner>\r\n </div>\r\n\r\n <!-- <div style=\"color: #666\">\r\n n={{newMessages.length}}, m={{messages.length}}, o={{olderMessages.length}},\r\n v={{maxVisibleMessages}}, M={{maxMessages}}\r\n </div> -->\r\n\r\n <ng-content select=\":not([data-before]):not(.inline-replies)\"></ng-content>\r\n</div>\r\n", styles: [":host{flex-grow:1;display:flex;flex-direction:column;opacity:1;transition:.2s opacity ease-in}.message-container{flex-grow:1;color:#111;background:#fff;padding:.5em 1em 3em .5em;opacity:1;transition:.5s opacity ease-in-out;position:relative}.message-container.no-scroll{height:auto;overflow-y:visible}.message-container.faded{opacity:.25}.message-container .overlay{position:absolute;inset:0;z-index:10}:host.fixed-height .message-container{overflow-y:auto}:host-context(.mat-dark-theme) .message-container{color:#fff;background:#111}.empty-state{text-align:center;margin:3em;color:#666}:host-context(.mat-dark-theme) .empty-state{color:#666}a.nav{position:absolute;right:.5em;z-index:10;text-align:center;opacity:0;transition:.4s opacity ease-in-out;pointer-events:none;border-radius:2em;background:#222}a.nav.visible{opacity:1;pointer-events:initial}.top-sticky{position:sticky;top:.5em;z-index:10}.bottom-sticky{position:sticky;bottom:3em;z-index:10}.loading-more{padding:2em;text-align:center;margin:0 auto;width:fit-content}@media (max-width: 400px){.message-container{padding:0 0 3em}}\n"] }]
410
+ }], ctorParameters: () => [{ type: i1.ChatBackendBase }, { type: i0.ElementRef }], propDecorators: { source: [{
411
+ type: Input
412
+ }], maxMessages: [{
413
+ type: Input
414
+ }], maxVisibleMessages: [{
415
+ type: Input
416
+ }], newestLast: [{
417
+ type: Input
418
+ }], holdNewMessages: [{
419
+ type: Input
420
+ }], showEmptyState: [{
421
+ type: Input
422
+ }], allowReplies: [{
423
+ type: Input
424
+ }], enableHoldOnClick: [{
425
+ type: Input
426
+ }], enableHoldOnScroll: [{
427
+ type: Input
428
+ }], customMenuItems: [{
429
+ type: Input
430
+ }], fixedHeight: [{
431
+ type: Input
432
+ }, {
433
+ type: HostBinding,
434
+ args: ['class.fixed-height']
435
+ }], selectedMessage: [{
436
+ type: Input
437
+ }], genericAvatarUrl: [{
438
+ type: Input
439
+ }], userSelected: [{
440
+ type: Output
441
+ }], reported: [{
442
+ type: Output
443
+ }], liked: [{
444
+ type: Output
445
+ }], unliked: [{
446
+ type: Output
447
+ }], usernameSelected: [{
448
+ type: Output
449
+ }], avatarSelected: [{
450
+ type: Output
451
+ }], shared: [{
452
+ type: Output
453
+ }], deleted: [{
454
+ type: Output
455
+ }], selected: [{
456
+ type: Output
457
+ }], messageEdited: [{
458
+ type: Output
459
+ }], sortOrderChanged: [{
460
+ type: Output
461
+ }], filterModeChanged: [{
462
+ type: Output
463
+ }], commentsQuery: [{
464
+ type: ViewChildren,
465
+ args: [CommentComponent]
466
+ }], messageContainer: [{
467
+ type: ViewChild,
468
+ args: ['messageContainer']
469
+ }] } });
470
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY29tbWVudC12aWV3LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL3Nkay9zcmMvbGliL2NvbW1lbnRzL2NvbW1lbnQtdmlldy9jb21tZW50LXZpZXcuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vcHJvamVjdHMvc2RrL3NyYy9saWIvY29tbWVudHMvY29tbWVudC12aWV3L2NvbW1lbnQtdmlldy5jb21wb25lbnQuaHRtbCJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsU0FBUyxFQUFFLEtBQUssRUFBRSxTQUFTLEVBQWMsTUFBTSxFQUFFLFdBQVcsRUFBRSxZQUFZLEVBQWEsTUFBTSxlQUFlLENBQUM7QUFDdEgsT0FBTyxFQUFxQixhQUFhLEVBQUUsVUFBVSxFQUFFLE1BQU0sZUFBZSxDQUFDO0FBQzdFLE9BQU8sRUFBRSxPQUFPLEVBQUUsWUFBWSxFQUFFLE1BQU0sTUFBTSxDQUFDO0FBSTdDLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLDhCQUE4QixDQUFDOzs7Ozs7OztBQVloRSxNQUFNLE9BQU8sb0JBQW9CO0lBQzdCLFlBQ1ksT0FBd0IsRUFDeEIsVUFBbUM7UUFEbkMsWUFBTyxHQUFQLE9BQU8sQ0FBaUI7UUFDeEIsZUFBVSxHQUFWLFVBQVUsQ0FBeUI7UUFVL0MsWUFBWTtRQUNaLGdCQUFnQjtRQUVSLGdCQUFXLEdBQUcsSUFBSSxZQUFZLEVBQUUsQ0FBQztRQUN6QyxnQkFBVyxHQUFnQixJQUFJLENBQUM7UUFDaEMsYUFBUSxHQUFrQixFQUFFLENBQUM7UUFFN0Isc0JBQWlCLEdBQUcsS0FBSyxDQUFDO1FBRTFCLGlCQUFZLEdBQUcsSUFBSSxPQUFPLENBQU8sQ0FBQyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDLENBQUM7UUFDakUsa0JBQWEsR0FBRyxLQUFLLENBQUM7UUFDdEIsa0JBQWEs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Z0JBQ0csZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csaUJBQWlCO3NCQUF6QixLQUFLO2dCQUNHLGtCQUFrQjtzQkFBMUIsS0FBSztnQkFDRyxlQUFlO3NCQUF2QixLQUFLO2dCQUNzQyxXQUFXO3NCQUF0RCxLQUFLOztzQkFBSSxXQUFXO3VCQUFDLG9CQUFvQjtnQkFDakMsZUFBZTtzQkFBdkIsS0FBSztnQkFDRyxnQkFBZ0I7c0JBQXhCLEtBQUs7Z0JBa0JhLFlBQVk7c0JBQTlCLE1BQU07Z0JBQ1ksUUFBUTtzQkFBMUIsTUFBTTtnQkFDWSxLQUFLO3NCQUF2QixNQUFNO2dCQUNZLE9BQU87c0JBQXpCLE1BQU07Z0JBQ1ksZ0JBQWdCO3NCQUFsQyxNQUFNO2dCQUNZLGNBQWM7c0JBQWhDLE1BQU07Z0JBQ1ksTUFBTTtzQkFBeEIsTUFBTTtnQkFDWSxPQUFPO3NCQUF6QixNQUFNO2dCQUNZLFFBQVE7c0JBQTFCLE1BQU07Z0JBQ1ksYUFBYTtzQkFBL0IsTUFBTTtnQkFDWSxnQkFBZ0I7c0JBQWxDLE1BQU07Z0JBQ1ksaUJBQWlCO3NCQUFuQyxNQUFNO2dCQUt5QixhQUFhO3NCQUE1QyxZQUFZO3VCQUFDLGdCQUFnQjtnQkFDQyxnQkFBZ0I7c0JBQTlDLFNBQVM7dUJBQUMsa0JBQWtCIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgQ29tcG9uZW50LCBJbnB1dCwgVmlld0NoaWxkLCBFbGVtZW50UmVmLCBPdXRwdXQsIEhvc3RCaW5kaW5nLCBWaWV3Q2hpbGRyZW4sIFF1ZXJ5TGlzdCB9IGZyb20gXCJAYW5ndWxhci9jb3JlXCI7XHJcbmltcG9ydCB7IFVzZXIsIENoYXRNZXNzYWdlLCBDb21tZW50c09yZGVyLCBGaWx0ZXJNb2RlIH0gZnJvbSAnQGJhbnRhL2NvbW1vbic7XHJcbmltcG9ydCB7IFN1YmplY3QsIFN1YnNjcmlwdGlvbiB9IGZyb20gJ3J4anMnO1xyXG5pbXBvcnQgeyBDaGF0QmFja2VuZEJhc2UgfSBmcm9tIFwiLi4vLi4vY2hhdC1iYWNrZW5kLWJhc2VcIjtcclxuaW1wb3J0IHsgQ2hhdFNvdXJjZUJhc2UgfSBmcm9tIFwiLi4vLi4vY2hhdC1zb3VyY2UtYmFzZVwiO1xyXG5pbXBvcnQgeyBNZXNzYWdlTWVudUl0ZW0gfSBmcm9tIFwiLi4vLi4vbWVzc2FnZS1tZW51LWl0ZW1cIjtcclxuaW1wb3J0IHsgQ29tbWVudENvbXBvbmVudCB9IGZyb20gXCIuLi9jb21tZW50L2NvbW1lbnQuY29tcG9uZW50XCI7XHJcblxyXG5leHBvcnQgaW50ZXJmYWNlIEVkaXRFdmVudCB7XHJcbiAgICBtZXNzYWdlOiBDaGF0TWVzc2FnZTtcclxuICAgIG5ld01lc3NhZ2U6IHN0cmluZztcclxufVxyXG5cclxuQENvbXBvbmVudCh7XHJcbiAgICBzZWxlY3RvcjogJ2JhbnRhLWNvbW1lbnQtdmlldycsXHJcbiAgICB0ZW1wbGF0ZVVybDogJy4vY29tbWVudC12aWV3LmNvbXBvbmVudC5odG1sJyxcclxuICAgIHN0eWxlVXJsczogWycuL2NvbW1lbnQtdmlldy5jb21wb25lbnQuc2NzcyddXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBDb21tZW50Vmlld0NvbXBvbmVudCB7XHJcbiAgICBjb25zdHJ1Y3RvcihcclxuICAgICAgICBwcml2YXRlIGJhY2tlbmQ6IENoYXRCYWNrZW5kQmFzZSxcclxuICAgICAgICBwcml2YXRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+XHJcbiAgICApIHtcclxuICAgIH1cclxuXHJcbiAgICAvLyNyZWdpb24gU291cmNlXHJcblxyXG4gICAgcHJpdmF0ZSBfc291cmNlOiBDaGF0U291cmNlQmFzZTtcclxuICAgIEBJbnB1dCgpIGdldCBzb3VyY2UoKSB7IHJldHVybiB0aGlzLl9zb3VyY2U7IH1cclxuICAgIHNldCBzb3VyY2UodmFsdWUpIHsgdGhpcy5zZXRTb3VyY2UodmFsdWUpOyB9XHJcblxyXG4gICAgLy8jZW5kcmVnaW9uXHJcbiAgICAvLyNyZWdpb24gRmllbGRzXHJcblxyXG4gICAgcHJpdmF0ZSBfc291cmNlU3VicyA9IG5ldyBTdWJzY3JpcHRpb24oKTtcclxuICAgIG1lbnVNZXNzYWdlOiBDaGF0TWVzc2FnZSA9IG51bGw7XHJcbiAgICBtZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSA9IFtdO1xyXG4gICAgY3VycmVudFVzZXI6IFVzZXI7XHJcbiAgICBjdXN0b21Tb3J0RW5hYmxlZCA9IGZhbHNlO1xyXG4gICAgbWFya1NvdXJjZUxvYWRlZDogKCkgPT4gdm9pZDtcclxuICAgIHNvdXJjZUxvYWRlZCA9IG5ldyBQcm9taXNlPHZvaWQ+KHIgPT4gdGhpcy5tYXJrU291cmNlTG9hZGVkID0gcik7XHJcbiAgICBpc1ZpZXdpbmdNb3JlID0gZmFsc2U7XHJcbiAgICBpc0xvYWRpbmdNb3JlID0gZmFsc2U7XHJcbiAgICBoYXNNb3JlID0gZmFsc2U7XHJcbiAgICBuZXdNZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSA9IFtdO1xyXG4gICAgb2xkZXJNZXNzYWdlczogQ2hhdE1lc3NhZ2VbXSA9IFtdO1xyXG5cclxuICAgIC8vI2VuZHJlZ2lvblxyXG4gICAgLy8jcmVnaW9uIElucHV0c1xyXG5cclxuICAgIEBJbnB1dCgpIG1heE1lc3NhZ2VzID0gMjAwMDtcclxuICAgIEBJbnB1dCgpIG1heFZpc2libGVNZXNzYWdlczogbnVtYmVyID0gMjAwO1xyXG4gICAgQElucHV0KCkgbmV3ZXN0TGFzdCA9IGZhbHNlO1xyXG4gICAgQElucHV0KCkgaG9sZE5ld01lc3NhZ2VzID0gZmFsc2U7XHJcbiAgICBASW5wdXQoKSBzaG93RW1wdHlTdGF0ZSA9IHRydWU7XHJcbiAgICBASW5wdXQoKSBhbGxvd1JlcGxpZXMgPSB0cnVlO1xyXG4gICAgQElucHV0KCkgZW5hYmxlSG9sZE9uQ2xpY2sgPSBmYWxzZTtcclxuICAgIEBJbnB1dCgpIGVuYWJsZUhvbGRPblNjcm9sbCA9IHRydWU7XHJcbiAgICBASW5wdXQoKSBjdXN0b21NZW51SXRlbXM6IE1lc3NhZ2VNZW51SXRlbVtdID0gW107XHJcbiAgICBASW5wdXQoKSBASG9zdEJpbmRpbmcoJ2NsYXNzLmZpeGVkLWhlaWdodCcpIGZpeGVkSGVpZ2h0OiBib29sZWFuO1xyXG4gICAgQElucHV0KCkgc2VsZWN0ZWRNZXNzYWdlOiBDaGF0TWVzc2FnZTtcclxuICAgIEBJbnB1dCgpIGdlbmVyaWNBdmF0YXJVcmw6IHN0cmluZztcclxuICAgIFxyXG4gICAgLy8jZW5kcmVnaW9uXHJcbiAgICAvLyNyZWdpb24gT3V0cHV0c1xyXG5cclxuICAgIHByaXZhdGUgX3NlbGVjdGVkID0gbmV3IFN1YmplY3Q8Q2hhdE1lc3NhZ2U+KCk7XHJcbiAgICBwcml2YXRlIF9saWtlZCA9IG5ldyBTdWJqZWN0PENoYXRNZXNzYWdlPigpO1xyXG4gICAgcHJpdmF0ZSBfdW5saWtlZCA9IG5ldyBTdWJqZWN0PENoYXRNZXNzYWdlPigpO1xyXG4gICAgcHJpdmF0ZSBfcmVwb3J0ZWQgPSBuZXcgU3ViamVjdDxDaGF0TWVzc2FnZT4oKTtcclxuICAgIHByaXZhdGUgX3VzZXJTZWxlY3RlZCA9IG5ldyBTdWJqZWN0PENoYXRNZXNzYWdlPigpO1xyXG4gICAgcHJpdmF0ZSBfdXNlcm5hbWVTZWxlY3RlZCA9IG5ldyBTdWJqZWN0PFVzZXI+KCk7XHJcbiAgICBwcml2YXRlIF9hdmF0YXJTZWxlY3RlZCA9IG5ldyBTdWJqZWN0PFVzZXI+KCk7XHJcbiAgICBwcml2YXRlIF9zaGFyZWQgPSBuZXcgU3ViamVjdDxDaGF0TWVzc2FnZT4oKTtcclxuICAgIHByaXZhdGUgX2RlbGV0ZWQgPSBuZXcgU3ViamVjdDxDaGF0TWVzc2FnZT4oKTtcclxuICAgIHByaXZhdGUgX21lc3NhZ2VFZGl0ZWQgPSBuZXcgU3ViamVjdDxFZGl0RXZlbnQ+KCk7XHJcbiAgICBwcml2YXRlIF9zb3J0T3JkZXJDaGFuZ2VkID0gbmV3IFN1YmplY3Q8Q29tbWVudHNPcmRlcj4oKTtcclxuICAgIHByaXZhdGUgX2ZpbHRlck1vZGVDaGFuZ2VkID0gbmV3IFN1YmplY3Q8RmlsdGVyTW9kZT4oKTtcclxuXHJcbiAgICBAT3V0cHV0KCkgcmVhZG9ubHkgdXNlclNlbGVjdGVkID0gdGhpcy5fdXNlclNlbGVjdGVkLmFzT2JzZXJ2YWJsZSgpO1xyXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IHJlcG9ydGVkID0gdGhpcy5fcmVwb3J0ZWQuYXNPYnNlcnZhYmxlKCk7XHJcbiAgICBAT3V0cHV0KCkgcmVhZG9ubHkgbGlrZWQgPSB0aGlzLl9saWtlZC5hc09ic2VydmFibGUoKTtcclxuICAgIEBPdXRwdXQoKSByZWFkb25seSB1bmxpa2VkID0gdGhpcy5fdW5saWtlZC5hc09ic2VydmFibGUoKTtcclxuICAgIEBPdXRwdXQoKSByZWFkb25seSB1c2VybmFtZVNlbGVjdGVkID0gdGhpcy5fdXNlcm5hbWVTZWxlY3RlZC5hc09ic2VydmFibGUoKTtcclxuICAgIEBPdXRwdXQoKSByZWFkb25seSBhdmF0YXJTZWxlY3RlZCA9IHRoaXMuX2F2YXRhclNlbGVjdGVkLmFzT2JzZXJ2YWJsZSgpO1xyXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IHNoYXJlZCA9IHRoaXMuX3NoYXJlZC5hc09ic2VydmFibGUoKTtcclxuICAgIEBPdXRwdXQoKSByZWFkb25seSBkZWxldGVkID0gdGhpcy5fZGVsZXRlZC5hc09ic2VydmFibGUoKTtcclxuICAgIEBPdXRwdXQoKSByZWFkb25seSBzZWxlY3RlZCA9IHRoaXMuX3NlbGVjdGVkLmFzT2JzZXJ2YWJsZSgpO1xyXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IG1lc3NhZ2VFZGl0ZWQgPSB0aGlzLl9tZXNzYWdlRWRpdGVkLmFzT2JzZXJ2YWJsZSgpO1xyXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IHNvcnRPcmRlckNoYW5nZWQgPSB0aGlzLl9zb3J0T3JkZXJDaGFuZ2VkLmFzT2JzZXJ2YWJsZSgpO1xyXG4gICAgQE91dHB1dCgpIHJlYWRvbmx5IGZpbHRlck1vZGVDaGFuZ2VkID0gdGhpcy5fZmlsdGVyTW9kZUNoYW5nZWQuYXNPYnNlcnZhYmxlKCk7XHJcblxyXG4gICAgLy8jZW5kcmVnaW9uIFxyXG4gICAgLy8jcmVnaW9uIFVJIEJpbmRpbmdzXHJcblxyXG4gICAgQFZpZXdDaGlsZHJlbihDb21tZW50Q29tcG9uZW50KSBjb21tZW50c1F1ZXJ5OiBRdWVyeUxpc3Q8Q29tbWVudENvbXBvbmVudD47XHJcbiAgICBAVmlld0NoaWxkKCdtZXNzYWdlQ29udGFpbmVyJykgbWVzc2FnZUNvbnRhaW5lcjogRWxlbWVudFJlZjxIVE1MRWxlbWVudD47XHJcbiAgICBnZXQgY29tbWVudHMoKSB7IHJldHVybiBBcnJheS5mcm9tKHRoaXMuY29tbWVudHNRdWVyeSk7IH1cclxuXHJcbiAgICAvLyNlbmRyZWdpb25cclxuXHJcbiAgICAvKipcclxuICAgICAqIFJldHVybnMgdHJ1ZSBpZiB0aGlzIG1lc3NhZ2UgY2FuIGJlIGZvdW5kIHdpdGhpbiBvbmUgb2YgdGhlIG1lc3NhZ2UgYnVmZmVycyAob2xkZXIsIGN1cnJlbnQsIG5ld2VyKVxyXG4gICAgICogQHBhcmFtIG1lc3NhZ2UgXHJcbiAgICAgKi9cclxuICAgIGlzTWVzc2FnZUxvYWRlZEluQ29udGV4dChtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIHJldHVybiB0aGlzLm9sZGVyTWVzc2FnZXMuZmluZCh4ID0+IHguaWQgPT09IG1lc3NhZ2UuaWQpXHJcbiAgICAgICAgICAgIHx8IHRoaXMubWVzc2FnZXMuZmluZCh4ID0+IHguaWQgPT09IG1lc3NhZ2UuaWQpXHJcbiAgICAgICAgICAgIHx8IHRoaXMubmV3TWVzc2FnZXMuZmluZCh4ID0+IHguaWQgPT09IG1lc3NhZ2UuaWQpO1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIGxvYWRNZXNzYWdlSW5Db250ZXh0KG1lc3NhZ2U6IENoYXRNZXNzYWdlKSB7XHJcbiAgICAgICAgYXdhaXQgdGhpcy5zb3VyY2VMb2FkZWQ7XHJcbiAgICAgICAgXHJcbiAgICAgICAgY29uc29sZS5sb2coYExvYWRpbmcgbWVzc2FnZSAke21lc3NhZ2UuaWR9IGluIGNvbnRleHQuLi5gKTtcclxuICAgICAgICB3aGlsZSAodGhpcy5oYXNNb3JlICYmICF0aGlzLmlzTWVzc2FnZUxvYWRlZEluQ29udGV4dChtZXNzYWdlKSkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgLi4uTmVlZCB0byBsb2FkIG1vcmUgY29tbWVudHMgdG8gZmluZCAke21lc3NhZ2UuaWR9YCk7XHJcbiAgICAgICAgICAgIGF3YWl0IHRoaXMuc2hvd01vcmUoKTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghdGhpcy5pc01lc3NhZ2VMb2FkZWRJbkNvbnRleHQobWVzc2FnZSkpIHtcclxuICAgICAgICAgICAgY29uc29sZS5lcnJvcihgRXJyb3Igd2hpbGUgbG9hZGluZyBtZXNzYWdlIGluIGNvbnRleHQ6IEZhaWxlZCB0byBmaW5kIG1lc3NhZ2UgJHttZXNzYWdlLmlkfSwgbWF5YmUgaXQgd2FzIGRlbGV0ZWQhYCk7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBwYWdlU2l6ZSA9IHRoaXMubWF4VmlzaWJsZU1lc3NhZ2VzO1xyXG4gICAgICAgIGxldCBpdGVtcyA9IFtdLmNvbmNhdCh0aGlzLm9sZGVyTWVzc2FnZXMsIHRoaXMubWVzc2FnZXMsIHRoaXMubmV3TWVzc2FnZXMpO1xyXG4gICAgICAgIGxldCBpbmRleCA9IGl0ZW1zLmZpbmRJbmRleCh4ID0+IHguaWQgPT09IG1lc3NhZ2UuaWQpO1xyXG5cclxuICAgICAgICBpZiAoaW5kZXggPCAwKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUuZXJyb3IoYEVycm9yIHdoaWxlIGxvYWRpbmcgbWVzc2FnZSBpbiBjb250ZXh0OiBNZXNzYWdlIHdhcyBub3QgcHJlc2VudCBpbiBtZXNzYWdlIGxpc3QhYCk7XHJcbiAgICAgICAgICAgIHJldHVybiBmYWxzZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGxldCBzdGFydEluZGV4ID0gTWF0aC5tYXgoMCwgaW5kZXggLSBwYWdlU2l6ZSAvIDIpOyAgICAgICAgXHJcbiAgICAgICAgdGhpcy5uZXdNZXNzYWdlcyA9IGl0ZW1zLnNwbGljZSgwLCBzdGFydEluZGV4KTtcclxuICAgICAgICB0aGlzLm1lc3NhZ2VzID0gaXRlbXMuc3BsaWNlKDAsIHBhZ2VTaXplKTtcclxuICAgICAgICB0aGlzLm9sZGVyTWVzc2FnZXMgPSBpdGVtcztcclxuICAgICAgICB0aGlzLmlzVmlld2luZ01vcmUgPSB0cnVlO1xyXG4gICAgfVxyXG5cclxuICAgIGdldCBzaG91bGRTaG93TmV3TWVzc2FnZUluZGljYXRvcigpIHtcclxuICAgICAgICByZXR1cm4gdGhpcy5pc1ZpZXdpbmdNb3JlIFxyXG4gICAgICAgICAgICB8fCB0aGlzLmN1c3RvbVNvcnRFbmFibGVkIFxyXG4gICAgICAgICAgICB8fCB0aGlzLnNvdXJjZS5maWx0ZXJNb2RlICE9PSBGaWx0ZXJNb2RlLkFMTFxyXG4gICAgICAgICAgICB8fCB0aGlzLm5ld01lc3NhZ2VzLmxlbmd0aCA+IDA7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IHNob3VsZEhvbGROZXdNZXNzYWdlcygpIHtcclxuICAgICAgICBpZiAodGhpcy5ob2xkTmV3TWVzc2FnZXMgfHwgdGhpcy5pc1ZpZXdpbmdNb3JlKSB7XHJcbiAgICAgICAgICAgIGNvbnNvbGUubG9nKGBob2xkaW5nIGR1ZSB0byBzZXR0aW5nc2ApO1xyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICh0aGlzLmVuYWJsZUhvbGRPblNjcm9sbCkge1xyXG4gICAgICAgICAgICBsZXQga2V5TWVzc2FnZTogQ2hhdE1lc3NhZ2U7XHJcblxyXG4gICAgICAgICAgICBpZiAodGhpcy5uZXdlc3RMYXN0KVxyXG4gICAgICAgICAgICAgICAga2V5TWVzc2FnZSA9IHRoaXMubWVzc2FnZXNbdGhpcy5tZXNzYWdlcy5sZW5ndGggLSAxXTtcclxuICAgICAgICAgICAgZWxzZVxyXG4gICAgICAgICAgICAgICAga2V5TWVzc2FnZSA9IHRoaXMubWVzc2FnZXNbMF07XHJcbiAgICAgICAgICAgIFxyXG4gICAgICAgICAgICBpZiAoa2V5TWVzc2FnZSkge1xyXG4gICAgICAgICAgICAgICAgY29uc3QgbWVzc2FnZUVsZW1lbnQgPSB0aGlzLmdldEVsZW1lbnRGb3JDb21tZW50KGtleU1lc3NhZ2UuaWQpO1xyXG4gICAgICAgICAgICAgICAgaWYgKG1lc3NhZ2VFbGVtZW50KSB7XHJcbiAgICAgICAgICAgICAgICAgICAgaWYgKCF0aGlzLmlzRWxlbWVudFZpc2libGUobWVzc2FnZUVsZW1lbnQpKSB7XHJcbiAgICAgICAgICAgICAgICAgICAgICAgIGNvbnNvbGUubG9nKGBrZXkgZWxlbWVudCBpcyBub3QgdmlzaWJsZWApO1xyXG4gICAgICAgICAgICAgICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xyXG4gICAgICAgICAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhga2V5IGVsZW1lbnQgaXMgdmlzaWJsZWApO1xyXG4gICAgICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICAgICAgY29uc29sZS5sb2coYGNvdWxkIG5vdCBmaW5kIGtleSBlbGVtZW50YCk7XHJcbiAgICAgICAgICAgICAgICB9XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICBjb25zb2xlLmxvZyhgY291bGQgbm90IGZpbmQga2V5IG1lc3NhZ2VgKTtcclxuICAgICAgICAgICAgfVxyXG5cclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgaXNFbGVtZW50VmlzaWJsZShlbGVtZW50OiBFbGVtZW50KSB7XHJcbiAgICAgICAgY29uc3QgZWxlbWVudFJlY3QgPSBlbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xyXG4gICAgICAgIHJldHVybiAhIWVsZW1lbnRSZWN0IFxyXG4gICAgICAgICAgICAmJiBlbGVtZW50UmVjdC5ib3R0b20gPj0gMFxyXG4gICAgICAgICAgICAmJiBlbGVtZW50UmVjdC5yaWdodCA+PSAwXHJcbiAgICAgICAgICAgICYmIGVsZW1lbnRSZWN0LmxlZnQgPD0gZG9jdW1lbnQuZG9jdW1lbnRFbGVtZW50LmNsaWVudFdpZHRoXHJcbiAgICAgICAgICAgICYmIGVsZW1lbnRSZWN0LnRvcCA8PSBkb2N1bWVudC5kb2N1bWVudEVsZW1lbnQuY2xpZW50SGVpZ2h0O1xyXG4gICAgfVxyXG5cclxuICAgIC8qKlxyXG4gICAgICogR2V0IHRoZSBDb21tZW50Q29tcG9uZW50IGluc3RhbnRpYXRlZCBmb3IgdGhlIGdpdmVuIENoYXRNZXNzYWdlLFxyXG4gICAgICogaWYgaXQgZXhpc3RzIGluIHRoZSBjdXJyZW50IHZpZXcuIE5vdGUgdGhhdCBtZXNzYWdlcyB3aGljaCBhcmUgbm90IFxyXG4gICAgICogY3VycmVudGx5IHNob3duIHRvIHRoZSB1c2VyIHdpbGwgbm90IHJldHVybiBhIENvbW1lbnRDb21wb25lbnQuXHJcbiAgICAgKiBAcGFyYW0gbWVzc2FnZSBcclxuICAgICAqIEByZXR1cm5zIFxyXG4gICAgICovXHJcbiAgICBnZXRDb21tZW50Q29tcG9uZW50Rm9yTWVzc2FnZShtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIGlmICghbWVzc2FnZSlcclxuICAgICAgICAgICAgdGhyb3cgbmV3IEVycm9yKGBZb3UgbXVzdCBwYXNzIGEgdmFsaWQgQ2hhdE1lc3NhZ2VgKTtcclxuICAgICAgICByZXR1cm4gdGhpcy5jb21tZW50cy5maW5kKHggPT4geC5tZXNzYWdlPy5pZCA9PT0gbWVzc2FnZS5pZCk7XHJcbiAgICB9XHJcblxyXG4gICAgc2F2ZUVkaXQobWVzc2FnZTogQ2hhdE1lc3NhZ2UsIG5ld01lc3NhZ2U6IHN0cmluZykge1xyXG4gICAgICAgIHRoaXMuX21lc3NhZ2VFZGl0ZWQubmV4dCh7IG1lc3NhZ2UsIG5ld01lc3NhZ2UgfSk7XHJcbiAgICB9XHJcblxyXG4gICAgbGlrZU1lc3NhZ2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UpIHtcclxuICAgICAgICB0aGlzLl9saWtlZC5uZXh0KG1lc3NhZ2UpO1xyXG4gICAgfVxyXG5cclxuICAgIHVubGlrZU1lc3NhZ2UobWVzc2FnZTogQ2hhdE1lc3NhZ2UpIHtcclxuICAgICAgICB0aGlzLl91bmxpa2VkLm5leHQobWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgcmVwb3J0TWVzc2FnZShtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIHRoaXMuX3JlcG9ydGVkLm5leHQobWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgc2VsZWN0TWVzc2FnZShtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIHRoaXMuX3NlbGVjdGVkLm5leHQobWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgc2VsZWN0TWVzc2FnZVVzZXIobWVzc2FnZTogQ2hhdE1lc3NhZ2UpIHtcclxuICAgICAgICB0aGlzLl91c2VyU2VsZWN0ZWQubmV4dChtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICBzZWxlY3RVc2VybmFtZSh1c2VyOiBVc2VyKSB7XHJcbiAgICAgICAgdGhpcy5fdXNlcm5hbWVTZWxlY3RlZC5uZXh0KHVzZXIpO1xyXG4gICAgfVxyXG5cclxuICAgIHNlbGVjdEF2YXRhcih1c2VyOiBVc2VyKSB7XHJcbiAgICAgICAgdGhpcy5fYXZhdGFyU2VsZWN0ZWQubmV4dCh1c2VyKTtcclxuICAgIH1cclxuXHJcbiAgICBzaGFyZWRNZXNzYWdlKG1lc3NhZ2U6IENoYXRNZXNzYWdlKSB7XHJcbiAgICAgICAgdGhpcy5fc2hhcmVkLm5leHQobWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgc3RhcnRFZGl0aW5nKG1lc3NhZ2U6IENoYXRNZXNzYWdlKSB7XHJcbiAgICAgICAgdGhpcy5tZXNzYWdlcy5mb3JFYWNoKG0gPT4gbS50cmFuc2llbnRTdGF0ZS5lZGl0aW5nID0gZmFsc2UpO1xyXG4gICAgICAgIG1lc3NhZ2UudHJhbnNpZW50U3RhdGUuZWRpdGluZyA9IHRydWU7XHJcbiAgICB9XHJcblxyXG4gICAgZGVsZXRlTWVzc2FnZShtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIHRoaXMuX2RlbGV0ZWQubmV4dChtZXNzYWdlKTtcclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIHNldFNvdXJjZSh2YWx1ZTogQ2hhdFNvdXJjZUJhc2UpIHtcclxuICAgICAgICB0aGlzLmN1c3RvbVNvcnRFbmFibGVkID0gdmFsdWU/LnNvcnRPcmRlciAhPT0gQ29tbWVudHNPcmRlci5ORVdFU1Q7XHJcbiAgICAgICAgdGhpcy5uZXdNZXNzYWdlcyA9IFtdO1xyXG4gICAgICAgIHRoaXMub2xkZXJNZXNzYWdlcyA9IFtdO1xyXG5cclxuICAgICAgICAod2luZG93IGFzIGFueSkuYmFudGFTb3VyY2VEZWJ1ZyA9IHZhbHVlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5fc291cmNlU3Vicykge1xyXG4gICAgICAgICAgICB0aGlzLl9zb3VyY2VTdWJzLnVuc3Vic2NyaWJlKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX3NvdXJjZVN1YnMgPSBudWxsO1xyXG4gICAgICAgIH1cclxuICAgICAgICB0aGlzLl9zb3VyY2UgPSB2YWx1ZTtcclxuXHJcbiAgICAgICAgaWYgKHZhbHVlKSB7XHJcbiAgICAgICAgICAgIGNvbnN0IG1lc3NhZ2VzID0gKHZhbHVlLm1lc3NhZ2VzIHx8IFtdKS5zbGljZSgpO1xyXG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VzID0gbWVzc2FnZXM7XHJcbiAgICAgICAgICAgIHRoaXMub2xkZXJNZXNzYWdlcyA9IG1lc3NhZ2VzLnNwbGljZSh0aGlzLm1heFZpc2libGVNZXNzYWdlcywgbWVzc2FnZXMubGVuZ3RoKTtcclxuICAgICAgICAgICAgdGhpcy5oYXNNb3JlID0gdHJ1ZTsgLy90aGlzLm9sZGVyTWVzc2FnZXMubGVuZ3RoID4gMDtcclxuXHJcbiAgICAgICAgICAgIHRoaXMuX3NvdXJjZVN1YnMgPSBuZXcgU3Vic2NyaXB0aW9uKCk7XHJcbiAgICAgICAgICAgIHRoaXMuX3NvdXJjZVN1YnMuYWRkKHRoaXMuX3NvdXJjZS5tZXNzYWdlUmVjZWl2ZWQuc3Vic2NyaWJlKG1zZyA9PiB0aGlzLm1lc3NhZ2VSZWNlaXZlZChtc2cpKSk7XHJcbiAgICAgICAgICAgIHRoaXMuX3NvdXJjZVN1YnMuYWRkKHRoaXMuX3NvdXJjZS5tZXNzYWdlU2VudC5zdWJzY3JpYmUobXNnID0+IHRoaXMubWVzc2FnZVNlbnQobXNnKSkpO1xyXG5cclxuICAgICAgICAgICAgdGhpcy5fc291cmNlU3Vicy5hZGQoXHJcbiAgICAgICAgICAgICAgICB0aGlzLmJhY2tlbmQudXNlckNoYW5nZWQuc3Vic2NyaWJlKHVzZXIgPT4gdGhpcy5jdXJyZW50VXNlciA9IHVzZXIpXHJcbiAgICAgICAgICAgICk7XHJcblxyXG4gICAgICAgICAgICB0aGlzLmdldEluaXRpYWxNZXNzYWdlcygpO1xyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBwcml2YXRlIGFzeW5jIGdldEluaXRpYWxNZXNzYWdlcygpIHtcclxuICAgICAgICBsZXQgbWVzc2FnZXMgPSAoYXdhaXQgdGhpcy5fc291cmNlLmdldEV4aXN0aW5nTWVzc2FnZXMoKSk7XHJcbiAgICAgICAgbWVzc2FnZXMuZm9yRWFjaChtID0+IG0udHJhbnNpZW50U3RhdGUgPz89IHt9KTtcclxuICAgICAgICB0aGlzLm1lc3NhZ2VzID0gdGhpcy5uZXdlc3RMYXN0ID8gbWVzc2FnZXMuc2xpY2UoKS5yZXZlcnNlKCkgOiBtZXNzYWdlcztcclxuICAgICAgICB0aGlzLnNvcnRNZXNzYWdlcygpO1xyXG4gICAgICAgIGlmICh0aGlzLm1hcmtTb3VyY2VMb2FkZWQpXHJcbiAgICAgICAgICAgIHRoaXMubWFya1NvdXJjZUxvYWRlZCgpO1xyXG4gICAgfVxyXG5cclxuICAgIG1lc3NhZ2VJZGVudGl0eShpbmRleDogbnVtYmVyLCBjaGF0TWVzc2FnZTogQ2hhdE1lc3NhZ2UpIHtcclxuICAgICAgICByZXR1cm4gY2hhdE1lc3NhZ2UuaWQ7XHJcbiAgICB9XHJcblxyXG4gICAgYXN5bmMgc2hvd05ldyhldmVudDogTW91c2VFdmVudCkge1xyXG4gICAgICAgIGxldCBuYXR1cmFsT3JkZXIgPSBDb21tZW50c09yZGVyLk5FV0VTVDtcclxuICAgICAgICBpZiAodGhpcy5zb3VyY2UgJiYgKHRoaXMuc291cmNlLnNvcnRPcmRlciAhPT0gbmF0dXJhbE9yZGVyIHx8IHRoaXMuc291cmNlLmZpbHRlck1vZGUgIT09IEZpbHRlck1vZGUuQUxMKSkge1xyXG4gICAgICAgICAgICBpZiAodGhpcy5zb3VyY2Uuc29ydE9yZGVyICE9PSBuYXR1cmFsT3JkZXIpXHJcbiAgICAgICAgICAgICAgICB0aGlzLl9zb3J0T3JkZXJDaGFuZ2VkLm5leHQobmF0dXJhbE9yZGVyKTtcclxuICAgICAgICAgICAgaWYgKHRoaXMuc291cmNlLmZpbHRlck1vZGUgIT09IEZpbHRlck1vZGUuQUxMKVxyXG4gICAgICAgICAgICAgICAgdGhpcy5fZmlsdGVyTW9kZUNoYW5nZWQubmV4dChGaWx0ZXJNb2RlLkFMTCk7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIHRoaXMuaXNWaWV3aW5nTW9yZSA9IGZhbHNlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5uZXdlc3RMYXN0KVxyXG4gICAgICAgICAgICB0aGlzLm1lc3NhZ2VzID0gdGhpcy5tZXNzYWdlcy5jb25jYXQodGhpcy5uZXdNZXNzYWdlcy5zcGxpY2UoMCwgdGhpcy5uZXdNZXNzYWdlcy5sZW5ndGgpKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm5ld01lc3NhZ2VzLnNwbGljZSgwLCB0aGlzLm5ld01lc3NhZ2VzLmxlbmd0aCkuY29uY2F0KHRoaXMubWVzc2FnZXMpO1xyXG4gICAgICAgIGxldCBvdmVyZmxvdyA9IHRoaXMubWVzc2FnZXMuc3BsaWNlKHRoaXMubWF4VmlzaWJsZU1lc3NhZ2VzLCB0aGlzLm1lc3NhZ2VzLmxlbmd0aCk7XHJcbiAgICAgICAgdGhpcy5vbGRlck1lc3NhZ2VzID0gb3ZlcmZsb3cuY29uY2F0KHRoaXMub2xkZXJNZXNzYWdlcyk7XHJcbiAgICAgICAgdGhpcy5vbGRlck1lc3NhZ2VzLnNwbGljZSh0aGlzLm1heE1lc3NhZ2VzIC0gdGhpcy5tYXhWaXNpYmxlTWVzc2FnZXMsIHRoaXMub2xkZXJNZXNzYWdlcy5sZW5ndGgpO1xyXG4gICAgICAgIHRoaXMuaGFzTW9yZSA9IHRoaXMub2xkZXJNZXNzYWdlcy5sZW5ndGggPiAwO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5tZXNzYWdlcy5sZW5ndGggPiAwKSB7XHJcbiAgICAgICAgICAgIGlmICh0aGlzLm5ld2VzdExhc3QpIHtcclxuICAgICAgICAgICAgICAgIHRoaXMuc2Nyb2xsVG9Db21tZW50KHRoaXMubWVzc2FnZXNbdGhpcy5tZXNzYWdlcy5sZW5ndGggLSAxXS5pZCk7XHJcbiAgICAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgICAgICB0aGlzLnNjcm9sbFRvQ29tbWVudCh0aGlzLm1lc3NhZ2VzWzBdLmlkKTtcclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuICAgIH1cclxuXHJcbiAgICBhc3luYyBzaG93TW9yZSgpIHtcclxuICAgICAgICB0aGlzLmlzVmlld2luZ01vcmUgPSB0cnVlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5vbGRlck1lc3NhZ2VzLmxlbmd0aCA+IDApIHtcclxuICAgICAgICAgICAgdGhpcy5pc0xvYWRpbmdNb3JlID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLmNvbmNhdCh0aGlzLm9sZGVyTWVzc2FnZXMuc3BsaWNlKDAsIDUwKSk7XHJcbiAgICAgICAgfVxyXG4gICAgICAgIHRoaXMuaXNMb2FkaW5nTW9yZSA9IHRydWU7XHJcblxyXG4gICAgICAgIGxldCBuZXh0UGFnZVNpemUgPSAyMDtcclxuICAgICAgICBsZXQgbGFzdE1lc3NhZ2U6IENoYXRNZXNzYWdlO1xyXG5cclxuICAgICAgICBpZiAodGhpcy5uZXdlc3RMYXN0KSB7XHJcbiAgICAgICAgICAgIGxhc3RNZXNzYWdlID0gdGhpcy5vbGRlck1lc3NhZ2VzWzBdID8/IHRoaXMubWVzc2FnZXNbMF07XHJcbiAgICAgICAgfSBlbHNlIHtcclxuICAgICAgICAgICAgbGFzdE1lc3NhZ2UgPSB0aGlzLm9sZGVyTWVzc2FnZXNbdGhpcy5vbGRlck1lc3NhZ2VzLmxlbmd0aCAtIDFdID8/IHRoaXMubWVzc2FnZXNbdGhpcy5tZXNzYWdlcy5sZW5ndGggLSAxXTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmICghbGFzdE1lc3NhZ2UpIHtcclxuICAgICAgICAgICAgdGhpcy5pc0xvYWRpbmdNb3JlID0gZmFsc2U7XHJcbiAgICAgICAgICAgIHRoaXMuaGFzTW9yZSA9IGZhbHNlO1xyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgfVxyXG5cclxuICAgICAgICBsZXQgbWVzc2FnZXMgPSBhd2FpdCB0aGlzLnNvdXJjZS5sb2FkQWZ0ZXIobGFzdE1lc3NhZ2UsIG5leHRQYWdlU2l6ZSk7XHJcblxyXG4gICAgICAgIGlmICh0aGlzLm5ld2VzdExhc3QpXHJcbiAgICAgICAgICAgIG1lc3NhZ2VzID0gbWVzc2FnZXMuc2xpY2UoKS5yZXZlcnNlKCk7XHJcbiAgICAgICAgXHJcbiAgICAgICAgbWVzc2FnZXMuZm9yRWFjaChtID0+IG0udHJhbnNpZW50U3RhdGUgPz89IHt9KTtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMubmV3ZXN0TGFzdClcclxuICAgICAgICAgICAgdGhpcy5tZXNzYWdlcyA9IG1lc3NhZ2VzLmNvbmNhdCh0aGlzLm1lc3NhZ2VzKTtcclxuICAgICAgICBlbHNlXHJcbiAgICAgICAgICAgIHRoaXMubWVzc2FnZXMgPSB0aGlzLm1lc3NhZ2VzLmNvbmNhdChtZXNzYWdlcyk7XHJcbiAgICAgICAgdGhpcy5pc0xvYWRpbmdNb3JlID0gZmFsc2U7XHJcbiAgICAgICAgaWYgKG1lc3NhZ2VzLmxlbmd0aCA9PT0gMCkge1xyXG4gICAgICAgICAgICBjb25zb2xlLmxvZyhgUmVhY2hlZCB0aGUgZW5kIG9mIHRoZSBsaXN0LmApO1xyXG4gICAgICAgICAgICB0aGlzLmhhc01vcmUgPSBmYWxzZTtcclxuICAgICAgICB9XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBhZGRNZXNzYWdlKG1lc3NhZ2U6IENoYXRNZXNzYWdlKSB7XHJcblxyXG4gICAgICAgIGlmICghbWVzc2FnZS50cmFuc2llbnRTdGF0ZSlcclxuICAgICAgICAgICAgbWVzc2FnZS50cmFuc2llbnRTdGF0ZSA/Pz0ge307XHJcbiAgICAgICAgXHJcbiAgICAgICAgbGV0IGRlc3RpbmF0aW9uID0gdGhpcy5tZXNzYWdlcztcclxuICAgICAgICBsZXQgYnVja2V0ID0gdGhpcy5vbGRlck1lc3NhZ2VzO1xyXG4gICAgICAgIGxldCBuZXdlc3RMYXN0ID0gdGhpcy5uZXdlc3RMYXN0O1xyXG5cclxuICAgICAgICBpZiAodGhpcy5zaG91bGRIb2xkTmV3TWVzc2FnZXMpIHtcclxuICAgICAgICAgICAgZGVzdGluYXRpb24gPSB0aGlzLm5ld01lc3NhZ2VzO1xyXG4gICAgICAgICAgICBidWNrZXQgPSBudWxsO1xyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgXHJcbiAgICAgICAgaWYgKG5ld2VzdExhc3QpIHtcclxuICAgICAgICAgICAgZGVzdGluYXRpb24ucHVzaChtZXNzYWdlKTtcclxuICAgICAgICAgICAgbGV0IG92ZXJmbG93ID0gZGVzdGluYXRpb24uc3BsaWNlKHRoaXMubWF4VmlzaWJsZU1lc3NhZ2VzLCBkZXN0aW5hdGlvbi5sZW5ndGgpO1xyXG4gICAgICAgICAgICBidWNrZXQ/LnB1c2goLi4ub3ZlcmZsb3cpO1xyXG4gICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgIGRlc3RpbmF0aW9uLnVuc2hpZnQobWVzc2FnZSk7XHJcbiAgICAgICAgICAgIGxldCBvdmVyZmxvdyA9IGRlc3RpbmF0aW9uLnNwbGljZSh0aGlzLm1heFZpc2libGVNZXNzYWdlcywgZGVzdGluYXRpb24ubGVuZ3RoKTtcclxuICAgICAgICAgICAgYnVja2V0Py51bnNoaWZ0KC4uLm92ZXJmbG93KTtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGlmIChidWNrZXQ/Lmxlbmd0aCA+IDApXHJcbiAgICAgICAgICAgIHRoaXMuaGFzTW9yZSA9IHRydWU7XHJcblxyXG4gICAgICAgIG1lc3NhZ2UucGFnaW5nQ3Vyc29yID0gU3RyaW5nKHRoaXMuaW5jcmVtZW50UGFnaW5nQ3Vyc29ycygpKTtcclxuICAgICAgICB0aGlzLnNvcnRNZXNzYWdlcygpO1xyXG4gICAgfVxyXG5cclxuICAgIHByaXZhdGUgaW5jcmVtZW50UGFnaW5nQ3Vyc29ycygpIHtcclxuICAgICAgICBpZiAodGhpcy5zb3VyY2Uuc29ydE9yZGVyICE9PSBDb21tZW50c09yZGVyLk5FV0VTVClcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGxldCBtYXhQYWdpbmdDdXJzb3IgPSAwO1xyXG4gICAgICAgIGZvciAobGV0IGdyb3VwIG9mIFt0aGlzLm1lc3NhZ2VzLCB0aGlzLm9sZGVyTWVzc2FnZXMsIHRoaXMubmV3TWVzc2FnZXNdKSB7XHJcbiAgICAgICAgICAgIGZvciAobGV0IG1lc3NhZ2Ugb2YgZ3JvdXApIHtcclxuICAgICAgICAgICAgICAgIGlmIChtZXNzYWdlLnBhZ2luZ0N1cnNvcikge1xyXG4gICAgICAgICAgICAgICAgICAgIGxldCBwYWdpbmdDdXJzb3IgPSBOdW1iZXIobWVzc2FnZS5wYWdpbmdDdXJzb3IpICsgMTtcclxuICAgICAgICAgICAgICAgICAgICBpZiAocGFnaW5nQ3Vyc29yID4gbWF4UGFnaW5nQ3Vyc29yKVxyXG4gICAgICAgICAgICAgICAgICAgICAgICBtYXhQYWdpbmdDdXJzb3IgPSBwYWdpbmdDdXJzb3I7XHJcbiAgICAgICAgICAgICAgICAgICAgbWVzc2FnZS5wYWdpbmdDdXJzb3IgPSBTdHJpbmcocGFnaW5nQ3Vyc29yKTtcclxuICAgICAgICAgICAgICAgIH1cclxuICAgICAgICAgICAgfVxyXG4gICAgICAgIH1cclxuXHJcbiAgICAgICAgcmV0dXJuIG1heFBhZ2luZ0N1cnNvcjtcclxuICAgIH1cclxuXHJcbiAgICAvKipcclxuICAgICAqIFdhaXQgZm9yIGFsbCBjdXJyZW50bHkgdmlzaWJsZSBjb21tZW50cyB0byBiZSBmdWxseSBsb2FkZWQsIGluY2x1ZGluZyBhbGwgYXR0YWNobWVudHMuXHJcbiAgICAgKiBEb2luZyB0aGlzIHdpbGwgcHJldmVudCBsYXlvdXQgc2hpZnQgd2hlbiBzY3JvbGxpbmcgdG8gYSBzcGVjaWZpYyBjb21tZW50LlxyXG4gICAgICovXHJcbiAgICBhc3luYyB3YWl0Rm9yQWxsQ29tbWVudHNUb0xvYWQoKSB7XHJcbiAgICAgICAgYXdhaXQgbmV3IFByb21pc2UociA9PiBzZXRUaW1lb3V0KHIsIDEwMCkpO1xyXG4gICAgICAgIGF3YWl0IHRoaXMuc291cmNlTG9hZGVkO1xyXG4gICAgICAgIGF3YWl0IFByb21pc2UuYWxsKHRoaXMuY29tbWVudHMubWFwKHggPT4geC53YWl0Rm9yTG9hZCgpKSk7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBzb3J0TWVzc2FnZXMoKSB7XHJcbiAgICAgICAgaWYgKCF0aGlzLnNvdXJjZSlcclxuICAgICAgICAgICAgcmV0dXJuO1xyXG4gICAgICAgIFxyXG4gICAgICAgIGxldCBzb3J0ZXI6IChhOiBDaGF0TWVzc2FnZSwgYjogQ2hhdE1lc3NhZ2UpID0+IG51bWJlcjtcclxuXHJcbiAgICAgICAgaWYgKHRoaXMuc291cmNlLnNvcnRPcmRlciA9PT0gQ29tbWVudHNPcmRlci5MSUtFUylcclxuICAgICAgICAgICAgc29ydGVyID0gKGEsIGIpID0+IGIubGlrZXMgLSBhLmxpa2VzO1xyXG4gICAgICAgIGVsc2UgaWYgKHRoaXMuc291cmNlLnNvcnRPcmRlciA9PT0gQ29tbWVudHNPcmRlci5ORVdFU1QpXHJcbiAgICAgICAgICAgIHNvcnRlciA9IChhLCBiKSA9PiAoYi5zZW50QXQgLSBhLnNlbnRBdCkgKiAodGhpcy5uZXdlc3RMYXN0ID8gLTEgOiAxKTtcclxuICAgICAgICBlbHNlIGlmICh0aGlzLnNvdXJjZS5zb3J0T3JkZXIgPT09IENvbW1lbnRzT3JkZXIuT0xERVNUKVxyXG4gICAgICAgICAgICBzb3J0ZXIgPSAoYSwgYikgPT4gKGEuc2VudEF0IC0gYi5zZW50QXQpICogKHRoaXMubmV3ZXN0TGFzdCA/IC0xIDogMSk7XHJcblxyXG4gICAgICAgIHRoaXMubWVzc2FnZXMuc29ydChzb3J0ZXIpO1xyXG4gICAgICAgIHRoaXMub2xkZXJNZXNzYWdlcy5zb3J0KHNvcnRlcik7XHJcbiAgICAgICAgdGhpcy5uZXdNZXNzYWdlcy5zb3J0KHNvcnRlcik7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBtZXNzYWdlUmVjZWl2ZWQobWVzc2FnZTogQ2hhdE1lc3NhZ2UpIHtcclxuICAgICAgICB0aGlzLmFkZE1lc3NhZ2UobWVzc2FnZSk7XHJcbiAgICB9XHJcblxyXG4gICAgaXNTY3JvbGxlZFRvTGF0ZXN0KCkge1xyXG4gICAgICAgIGlmICghdGhpcy5tZXNzYWdlQ29udGFpbmVyKVxyXG4gICAgICAgICAgICByZXR1cm4gZmFsc2U7XHJcblxyXG4gICAgICAgIGNvbnN0IGVsID0gdGhpcy5tZXNzYWdlQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQ7XHJcbiAgICAgICAgY29uc3QgY3VycmVudFNjcm9sbCA9IGVsLnNjcm9sbFRvcDtcclxuICAgICAgICBjb25zdCBjdXJyZW50VG90YWwgPSBlbC5zY3JvbGxIZWlnaHQgLSBlbC5vZmZzZXRIZWlnaHQ7XHJcblxyXG4gICAgICAgIHJldHVybiBjdXJyZW50U2Nyb2xsID4gY3VycmVudFRvdGFsIC0gMTA7XHJcbiAgICB9XHJcblxyXG4gICAgcHJpdmF0ZSBtZXNzYWdlU2VudChtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIHRoaXMuYWRkTWVzc2FnZShtZXNzYWdlKTtcclxuXHJcbiAgICAgICAgaWYgKCF0aGlzLm1lc3NhZ2VDb250YWluZXIpXHJcbiAgICAgICAgICAgIHJldHVybjtcclxuXHJcbiAgICAgICAgdGhpcy5zY3JvbGxUb0xhdGVzdCgpO1xyXG4gICAgfVxyXG5cclxuICAgIHNjcm9sbFRvTGF0ZXN0KCkge1xyXG4gICAgICAgIGlmICghdGhpcy5tZXNzYWdlQ29udGFpbmVyKSB7XHJcbiAgICAgICAgICAgIHJldHVybjtcclxuICAgICAgICB9XHJcblxyXG4gICAgICAgIGNvbnN0IGVsID0gdGhpcy5tZXNzYWdlQ29udGFpbmVyLm5hdGl2ZUVsZW1lbnQ7XHJcblxyXG4gICAgICAgIGVsLnNjcm9sbEludG9WaWV3KHsgYmxvY2s6ICdzdGFydCcgfSk7XHJcbiAgICAgICAgLy9lbC5zY3JvbGxUb3AgPSBlbC5zY3JvbGxIZWlnaHQ7XHJcbiAgICB9XHJcblxyXG4gICAgZ2V0IGVsZW1lbnQoKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudFJlZi5uYXRpdmVFbGVtZW50O1xyXG4gICAgfVxyXG5cclxuICAgIGFzeW5jIHNjcm9sbFRvQ29tbWVudChjb21tZW50SWQ6IENoYXRNZXNzYWdlWydpZCddKSB7XHJcbiAgICAgICAgaWYgKHR5cGVvZiB3aW5kb3cgPT09ICd1bmRlZmluZWQnKVxyXG4gICAgICAgICAgICByZXR1cm47XHJcbiAgICAgICAgXHJcbiAgICAgICAgYXdhaXQgdGhpcy53YWl0Rm9yQWxsQ29tbWVudHNUb0xvYWQoKTtcclxuXHJcbiAgICAgICAgY29uc3QgY29tbWVudCA9IHRoaXMuZ2V0RWxlbWVudEZvckNvbW1lbnQoY29tbWVudElkKTtcclxuICAgICAgICBpZiAoY29tbWVudCkge1xyXG4gICAgICAgICAgICBjb21tZW50LnNjcm9sbEludG9WaWV3KHtcclxuICAgICAgICAgICAgICAgIGlubGluZTogJ2NlbnRlcicsXHJcbiAgICAgICAgICAgICAgICBibG9jazogJ2NlbnRlcidcclxuICAgICAgICAgICAgfSk7XHJcbiAgICAgICAgfVxyXG4gICAgfVxyXG5cclxuICAgIGdldEVsZW1lbnRGb3JDb21tZW50KGNvbW1lbnRJZDogc3RyaW5nKSB7XHJcbiAgICAgICAgcmV0dXJuIHRoaXMuZWxlbWVudC5xdWVyeVNlbGVjdG9yKGBbZGF0YS1jb21tZW50LWlkPVwiJHtjb21tZW50SWR9XCJdYCk7XHJcbiAgICB9XHJcblxyXG4gICAgbWVudGlvbnNNZShtZXNzYWdlOiBDaGF0TWVzc2FnZSkge1xyXG4gICAgICAgIGlmICghdGhpcy5jdXJyZW50VXNlcilcclxuICAgICAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG5cclxuICAgICAgICBpZiAobWVzc2FnZS5tZXNzYWdlLmluY2x1ZGVzKGBAJHt0aGlzLmN1cnJlbnRVc2VyLnVzZXJuYW1lfWApKVxyXG4gICAgICAgICAgICByZXR1cm4gdHJ1ZTtcclxuXHJcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xyXG4gICAgfVxyXG59XHJcbiIsIjxkaXYgY2xhc3M9XCJtZXNzYWdlLWNvbnRhaW5lclwiICNtZXNzYWdlQ29udGFpbmVyPlxyXG4gICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwiW2RhdGEtYmVmb3JlXVwiPjwvbmctY29udGVudD5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwidG9wLXN0aWNreVwiPlxyXG4gICAgICAgIDxhICpuZ0lmPVwiIW5ld2VzdExhc3RcIiBtYXQtYnV0dG9uIGNsYXNzPVwibmF2XCIgW2NsYXNzLnZpc2libGVdPVwic2hvdWxkU2hvd05ld01lc3NhZ2VJbmRpY2F0b3JcIiBocmVmPVwiamF2YXNjcmlwdDo7XCIgKGNsaWNrKT1cInNob3dOZXcoJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICA8bWF0LWljb24+ZmlsZV91cGxvYWQ8L21hdC1pY29uPlxyXG4gICAgICAgICAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibmV3TWVzc2FnZXMubGVuZ3RoID49IDFcIj5cclxuICAgICAgICAgICAgICAgIE5ldyAoe3tuZXdNZXNzYWdlcy5sZW5ndGh9fSlcclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJuZXdNZXNzYWdlcy5sZW5ndGggPT0gMFwiPlxyXG4gICAgICAgICAgICAgICAgTmV3ZXN0XHJcbiAgICAgICAgICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgICAgIDwvYT5cclxuICAgIDwvZGl2PlxyXG4gICAgPGEgbWF0LWJ1dHRvbiBjbGFzcz1cIm5hdlwiIFtjbGFzcy52aXNpYmxlXT1cIm5ld2VzdExhc3QgJiYgaGFzTW9yZSAmJiAhaXNMb2FkaW5nTW9yZVwiIGhyZWY9XCJqYXZhc2NyaXB0OjtcIiAoY2xpY2spPVwic2hvd01vcmUoKVwiPlNob3cgZWFybGllcjwvYT5cclxuXHJcbiAgICA8bmctY29udGFpbmVyICpuZ0lmPVwibWVzc2FnZXMubGVuZ3RoID09PSAwXCI+XHJcbiAgICAgICAgPGRpdiBjbGFzcz1cImVtcHR5LXN0YXRlXCIgKm5nSWY9XCJzaG93RW1wdHlTdGF0ZVwiPlxyXG4gICAgICAgICAgICBCZSB0aGUgZmlyc3QgdG8gY29tbWVudCFcclxuICAgICAgICA8L2Rpdj5cclxuICAgIDwvbmctY29udGFpbmVyPlxyXG4gICAgPG5nLWNvbnRhaW5lciAqbmdGb3I9XCJsZXQgbWVzc2FnZSBvZiBtZXNzYWdlczsgdHJhY2tCeTogbWVzc2FnZUlkZW50aXR5XCI+XHJcbiAgICAgICAgPGJhbnRhLWNvbW1lbnRcclxuICAgICAgICAgICAgKm5nSWY9XCIhbWVzc2FnZS5oaWRkZW5cIlxyXG4gICAgICAgICAgICBjbGFzcz1cImFiYnJldmlhdGVkXCJcclxuICAgICAgICAgICAgXHJcbiAgICAgICAgICAgIFtjdXN0b21NZW51SXRlbXNdPVwiY3VzdG9tTWVudUl0ZW1zXCJcclxuICAgICAgICAgICAgW21lc3NhZ2VdPVwibWVzc2FnZVwiXHJcbiAgICAgICAgICAgIFttaW5lXT1cImN1cnJlbnRVc2VyPy5pZCA9PT0gbWVzc2FnZS51c2VyPy5pZFwiXHJcbiAgICAgICAgICAgIFtwZXJtaXNzaW9uc109XCJzb3VyY2U/LnBlcm1pc3Npb25zXCJcclxuICAgICAgICAgICAgW3Nob3dSZXBseUFjdGlvbl09XCJhbGxvd1JlcGxpZXNcIlxyXG4gICAgICAgICAgICBbZWRpdGluZ109XCJtZXNzYWdlLnRyYW5zaWVudFN0YXRlLmVkaXRpbmdcIlxyXG4gICAgICAgICAgICBbZ2VuZXJpY0F2YXRhclVybF09XCJnZW5lcmljQXZhdGFyVXJsXCJcclxuICAgICAgICAgICAgW3JlYWRvbmx5XT1cInNvdXJjZT8ucmVhZG9ubHlcIlxyXG4gICAgICAgICAgICAoY2xpY2spPVwiZW5hYmxlSG9sZE9uQ2xpY2sgPyAoaG9sZE5ld01lc3NhZ2VzID0gdHJ1ZSkgOiB1bmRlZmluZWRcIlxyXG4gICAgICAgICAgICAoZWRpdFN0YXJ0ZWQpPVwic3RhcnRFZGl0aW5nKG1lc3NhZ2UpXCJcclxuICAgICAgICAgICAgKGRlbGV0ZWQpPVwiZGVsZXRlTWVzc2FnZShtZXNzYWdlKVwiXHJcbiAgICAgICAgICAgIChlZGl0RW5kZWQpPVwibWVzc2FnZS50cmFuc2llbnRTdGF0ZS5lZGl0aW5nID0gZmFsc2VcIlxyXG4gICAgICAgICAgICAoZWRpdGVkKT1cInNhdmVFZGl0KG1lc3NhZ2UsICRldmVudClcIlxyXG4gICAgICAgICAgICAodXNlclNlbGVjdGVkKT1cInNlbGVjdE1lc3NhZ2VVc2VyKG1lc3NhZ2UpXCJcclxuICAgICAgICAgICAgKGF2YXRhclNlbGVjdGVkKT1cInNlbGVjdEF2YXRhcigkZXZlbnQpXCJcclxuICAgICAgICAgICAgKHVzZXJuYW1lU2VsZWN0ZWQpPVwic2VsZWN0VXNlcm5hbWUoJGV2ZW50KVwiXHJcbiAgICAgICAgICAgIChsaWtlZCk9XCJsaWtlTWVzc2FnZShtZXNzYWdlKVwiXHJcbiAgICAgICAgICAgICh1bmxpa2VkKT1cInVubGlrZU1lc3NhZ2UobWVzc2FnZSlcIlxyXG4gICAgICAgICAgICAocmVwb3J0ZWQpPVwicmVwb3J0TWVzc2FnZShtZXNzYWdlKVwiXHJcbiAgICAgICAgICAgIChzZWxlY3RlZCk9XCJzZWxlY3RNZXNzYWdlKG1lc3NhZ2UpXCJcclxuICAgICAgICAgICAgKHNoYXJlZCk9XCJzaGFyZWRNZXNzYWdlKCRldmVudClcIlxyXG4gICAgICAgICAgICA+PC9iYW50YS1jb21tZW50PlxyXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpbmxpbmUtcmVwbGllcy1jb250YWluZXJcIiAqbmdJZj1cInNlbGVjdGVkTWVzc2FnZSA9PT0gbWVzc2FnZVwiPlxyXG4gICAgICAgICAgICA8bmctY29udGVudCBzZWxlY3Q9XCIuaW5saW5lLXJlcGxpZXNcIj48L25nLWNvbnRlbnQ+XHJcbiAgICAgICAgPC9kaXY+XHJcbiAgICA8L25nLWNvbnRhaW5lcj5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwibmF2LXBvaW50IGJvdHRvbS1zdGlja3lcIj5cclxuICAgICAgICA8YSAqbmdJZj1cIm5ld2VzdExhc3RcIiBtYXQtYnV0dG9uIGNsYXNzPVwibmF2XCIgW2NsYXNzLnZpc2libGVdPVwic2hvdWxkU2hvd05ld01lc3NhZ2VJbmRpY2F0b3JcIiBocmVmPVwiamF2YXNjcmlwdDo7XCIgKGNsaWNrKT1cInNob3dOZXcoJGV2ZW50KVwiPlxyXG4gICAgICAgICAgICA8bWF0LWljb24+ZmlsZV9kb3dubG9hZDwvbWF0LWljb24+XHJcbiAgICAgICAgICAgIDxuZy1jb250YWluZXIgKm5nSWY9XCJuZXdNZXNzYWdlcy5sZW5ndGggPj0gMVwiPlxyXG4gICAgICAgICAgICAgICAgTmV3ICh7e25ld01lc3NhZ2VzLmxlbmd0aH19KVxyXG4gICAgICAgICAgICA8L25nLWNvbnRhaW5lcj5cclxuICAgICAgICAgICAgPG5nLWNvbnRhaW5lciAqbmdJZj1cIm5ld01lc3NhZ2VzLmxlbmd0aCA9PSAwXCI+XHJcbiAgICAgICAgICAgICAgICBOZXdlc3RcclxuICAgICAgICAgICAgPC9uZy1jb250YWluZXI+XHJcbiAgICAgICAgPC9hPlxyXG4gICAgPC9kaXY+XHJcbiAgICA8YSBtYXQtYnV0dG9uIGNsYXNzPVwibmF2XCIgW2NsYXNzLnZpc2libGVdPVwiIW5ld2VzdExhc3QgJiYgaGFzTW9yZSAmJiAhaXNMb2FkaW5nTW9yZVwiIGhyZWY9XCJqYXZhc2NyaXB0OjtcIiAoY2xpY2spPVwic2hvd01vcmUoKVwiPlNob3cgbW9yZTwvYT5cclxuXHJcbiAgICA8ZGl2IGNsYXNzPVwibG9hZGluZy1tb3JlXCIgKm5nSWY9XCJpc0xvYWRpbmdNb3JlXCI+XHJcbiAgICAgICAgPG1hdC1zcGlubmVyPjwvbWF0LXNwaW5uZXI+XHJcbiAgICA8L2Rpdj5cclxuXHJcbiAgICA8IS0tIDxkaXYgc3R5bGU9XCJjb2xvcjogIzY2NlwiPlxyXG4gICAgICAgIG49e3tuZXdNZXNzYWdlcy5sZW5ndGh9fSwgbT17e21lc3NhZ2VzLmxlbmd0aH19LCBvPXt7b2xkZXJNZXNzYWdlcy5sZW5ndGh9fSxcclxuICAgICAgICB2PXt7bWF4VmlzaWJsZU1lc3NhZ2VzfX0sIE09e3ttYXhNZXNzYWdlc319XHJcbiAgICA8L2Rpdj4gLS0+XHJcblxyXG4gICAgPG5nLWNvbnRlbnQgc2VsZWN0PVwiOm5vdChbZGF0YS1iZWZvcmVdKTpub3QoLmlubGluZS1yZXBsaWVzKVwiPjwvbmctY29udGVudD5cclxuPC9kaXY+XHJcbiJdfQ==