@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.
- package/{esm2020 → esm2022}/banta-sdk.mjs +4 -4
- package/{esm2020 → esm2022}/lib/attachment-scraper.mjs +1 -1
- package/esm2022/lib/banta/banta.component.mjs +204 -0
- package/{esm2020 → esm2022}/lib/banta-logo.component.mjs +11 -11
- package/esm2022/lib/banta-sdk.module.mjs +143 -0
- package/esm2022/lib/chat/banta-chat/banta-chat.component.mjs +187 -0
- package/esm2022/lib/chat/chat-message/chat-message.component.mjs +62 -0
- package/esm2022/lib/chat/chat-view/chat-view.component.mjs +170 -0
- package/{esm2020 → esm2022}/lib/chat/chat.module.mjs +51 -51
- package/{esm2020 → esm2022}/lib/chat/index.mjs +5 -5
- package/esm2022/lib/chat/live-chat-message.component.mjs +80 -0
- package/{esm2020 → esm2022}/lib/chat-backend-base.mjs +30 -30
- package/esm2022/lib/chat-backend.mjs +163 -0
- package/{esm2020 → esm2022}/lib/chat-source-base.mjs +1 -1
- package/esm2022/lib/chat-source.mjs +233 -0
- package/esm2022/lib/comments/attachment-button/attachment-button.component.mjs +76 -0
- package/esm2022/lib/comments/attachment-scraper.directive.mjs +107 -0
- package/esm2022/lib/comments/banta-comments/banta-comments.component.mjs +739 -0
- package/esm2022/lib/comments/comment/comment.component.mjs +175 -0
- package/esm2022/lib/comments/comment-field/comment-field.component.mjs +401 -0
- package/esm2022/lib/comments/comment-sort/comment-sort.component.mjs +37 -0
- package/esm2022/lib/comments/comment-view/comment-view.component.mjs +470 -0
- package/esm2022/lib/comments/comments.module.mjs +111 -0
- package/{esm2020 → esm2022}/lib/comments/index.mjs +10 -10
- package/esm2022/lib/comments/live-comment.component.mjs +80 -0
- package/{esm2020 → esm2022}/lib/comments/reply-send-options.directive.mjs +13 -13
- package/esm2022/lib/common/attachment/attachment.component.mjs +112 -0
- package/{esm2020 → esm2022}/lib/common/attachments/attachments.component.mjs +75 -75
- package/{esm2020 → esm2022}/lib/common/common.module.mjs +68 -68
- package/{esm2020 → esm2022}/lib/common/index.mjs +10 -10
- package/{esm2020 → esm2022}/lib/common/lazy-connection.mjs +14 -14
- package/esm2022/lib/common/lightbox/lightbox.component.mjs +31 -0
- package/esm2022/lib/common/markdown-to-html.pipe.mjs +89 -0
- package/esm2022/lib/common/mention-linker.pipe.mjs +35 -0
- package/esm2022/lib/common/timer-pool.service.mjs +83 -0
- package/esm2022/lib/common/timestamp.component.mjs +123 -0
- package/{esm2020 → esm2022}/lib/common/trust-resource-url.pipe.mjs +22 -22
- package/esm2022/lib/emoji/emoji-selector-button.component.mjs +115 -0
- package/esm2022/lib/emoji/emoji-selector-panel/emoji-selector-panel.component.mjs +98 -0
- package/{esm2020 → esm2022}/lib/emoji/emoji.module.mjs +55 -55
- package/{esm2020 → esm2022}/lib/emoji/emojis.mjs +6507 -6507
- package/{esm2020 → esm2022}/lib/emoji/index.mjs +4 -4
- package/esm2022/lib/giphy-attachments.mjs +16 -0
- package/{esm2020 → esm2022}/lib/index.mjs +19 -19
- package/{esm2020 → esm2022}/lib/live-message.component.mjs +61 -61
- package/{esm2020 → esm2022}/lib/message-menu-item.mjs +1 -1
- package/{esm2020 → esm2022}/lib/sdk-options.mjs +1 -1
- package/esm2022/lib/static-chat-source.mjs +71 -0
- package/esm2022/lib/tweet-attachments.mjs +13 -0
- package/esm2022/lib/url-attachments.mjs +42 -0
- package/esm2022/lib/youtube-attachments.mjs +29 -0
- package/{esm2020 → esm2022}/public-api.mjs +4 -4
- package/{fesm2020 → fesm2022}/banta-sdk.mjs +10753 -10754
- package/fesm2022/banta-sdk.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/attachment-scraper.d.ts +15 -15
- package/lib/banta/banta.component.d.ts +58 -58
- package/lib/banta-logo.component.d.ts +5 -5
- package/lib/banta-sdk.module.d.ts +31 -31
- package/lib/chat/banta-chat/banta-chat.component.d.ts +70 -70
- package/lib/chat/chat-message/chat-message.component.d.ts +21 -21
- package/lib/chat/chat-view/chat-view.component.d.ts +52 -52
- package/lib/chat/chat.module.d.ts +15 -15
- package/lib/chat/index.d.ts +5 -5
- package/lib/chat/live-chat-message.component.d.ts +23 -23
- package/lib/chat-backend-base.d.ts +36 -36
- package/lib/chat-backend.d.ts +55 -55
- package/lib/chat-source-base.d.ts +44 -44
- package/lib/chat-source.d.ts +65 -65
- package/lib/comments/attachment-button/attachment-button.component.d.ts +17 -17
- package/lib/comments/attachment-scraper.directive.d.ts +21 -21
- package/lib/comments/banta-comments/banta-comments.component.d.ts +196 -196
- package/lib/comments/comment/comment.component.d.ts +72 -72
- package/lib/comments/comment-field/comment-field.component.d.ts +89 -89
- package/lib/comments/comment-sort/comment-sort.component.d.ts +12 -12
- package/lib/comments/comment-view/comment-view.component.d.ts +121 -121
- package/lib/comments/comments.module.d.ts +30 -30
- package/lib/comments/index.d.ts +10 -10
- package/lib/comments/live-comment.component.d.ts +23 -23
- package/lib/comments/reply-send-options.directive.d.ts +5 -5
- package/lib/common/attachment/attachment.component.d.ts +33 -33
- package/lib/common/attachments/attachments.component.d.ts +26 -26
- package/lib/common/common.module.d.ts +19 -19
- package/lib/common/index.d.ts +10 -10
- package/lib/common/lazy-connection.d.ts +6 -6
- package/lib/common/lightbox/lightbox.component.d.ts +14 -14
- package/lib/common/markdown-to-html.pipe.d.ts +15 -15
- package/lib/common/mention-linker.pipe.d.ts +13 -13
- package/lib/common/timer-pool.service.d.ts +15 -15
- package/lib/common/timestamp.component.d.ts +19 -19
- package/lib/common/trust-resource-url.pipe.d.ts +10 -10
- package/lib/emoji/emoji-selector-button.component.d.ts +30 -30
- package/lib/emoji/emoji-selector-panel/emoji-selector-panel.component.d.ts +26 -26
- package/lib/emoji/emoji.module.d.ts +16 -16
- package/lib/emoji/emojis.d.ts +6507 -6507
- package/lib/emoji/index.d.ts +4 -4
- package/lib/giphy-attachments.d.ts +5 -5
- package/lib/index.d.ts +19 -19
- package/lib/live-message.component.d.ts +22 -22
- package/lib/message-menu-item.d.ts +6 -6
- package/lib/sdk-options.d.ts +5 -5
- package/lib/static-chat-source.d.ts +42 -42
- package/lib/tweet-attachments.d.ts +5 -5
- package/lib/url-attachments.d.ts +14 -14
- package/lib/youtube-attachments.d.ts +5 -5
- package/package.json +14 -20
- package/public-api.d.ts +1 -1
- package/esm2020/lib/banta/banta.component.mjs +0 -204
- package/esm2020/lib/banta-sdk.module.mjs +0 -143
- package/esm2020/lib/chat/banta-chat/banta-chat.component.mjs +0 -187
- package/esm2020/lib/chat/chat-message/chat-message.component.mjs +0 -62
- package/esm2020/lib/chat/chat-view/chat-view.component.mjs +0 -170
- package/esm2020/lib/chat/live-chat-message.component.mjs +0 -80
- package/esm2020/lib/chat-backend.mjs +0 -163
- package/esm2020/lib/chat-source.mjs +0 -233
- package/esm2020/lib/comments/attachment-button/attachment-button.component.mjs +0 -76
- package/esm2020/lib/comments/attachment-scraper.directive.mjs +0 -107
- package/esm2020/lib/comments/banta-comments/banta-comments.component.mjs +0 -740
- package/esm2020/lib/comments/comment/comment.component.mjs +0 -175
- package/esm2020/lib/comments/comment-field/comment-field.component.mjs +0 -401
- package/esm2020/lib/comments/comment-sort/comment-sort.component.mjs +0 -37
- package/esm2020/lib/comments/comment-view/comment-view.component.mjs +0 -470
- package/esm2020/lib/comments/comments.module.mjs +0 -111
- package/esm2020/lib/comments/live-comment.component.mjs +0 -80
- package/esm2020/lib/common/attachment/attachment.component.mjs +0 -112
- package/esm2020/lib/common/lightbox/lightbox.component.mjs +0 -31
- package/esm2020/lib/common/markdown-to-html.pipe.mjs +0 -89
- package/esm2020/lib/common/mention-linker.pipe.mjs +0 -35
- package/esm2020/lib/common/timer-pool.service.mjs +0 -83
- package/esm2020/lib/common/timestamp.component.mjs +0 -123
- package/esm2020/lib/emoji/emoji-selector-button.component.mjs +0 -116
- package/esm2020/lib/emoji/emoji-selector-panel/emoji-selector-panel.component.mjs +0 -98
- package/esm2020/lib/giphy-attachments.mjs +0 -16
- package/esm2020/lib/static-chat-source.mjs +0 -71
- package/esm2020/lib/tweet-attachments.mjs +0 -13
- package/esm2020/lib/url-attachments.mjs +0 -42
- package/esm2020/lib/youtube-attachments.mjs +0 -29
- package/fesm2015/banta-sdk.mjs +0 -11181
- package/fesm2015/banta-sdk.mjs.map +0 -1
- 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==
|