@ctrl/ngx-emoji-mart 8.1.0 → 9.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 (54) hide show
  1. package/README.md +39 -14
  2. package/anchors.component.d.ts +1 -1
  3. package/category.component.d.ts +3 -3
  4. package/esm2022/anchors.component.mjs +100 -0
  5. package/esm2022/category.component.mjs +409 -0
  6. package/esm2022/emoji-frequently.service.mjs +90 -0
  7. package/esm2022/emoji-search.service.mjs +178 -0
  8. package/esm2022/ngx-emoji/emoji.component.mjs +299 -0
  9. package/esm2022/ngx-emoji/emoji.module.mjs +17 -0
  10. package/esm2022/ngx-emoji/emoji.service.mjs +145 -0
  11. package/esm2022/picker.component.mjs +522 -0
  12. package/esm2022/picker.module.mjs +40 -0
  13. package/esm2022/preview.component.mjs +206 -0
  14. package/esm2022/search.component.mjs +175 -0
  15. package/esm2022/skins.component.mjs +107 -0
  16. package/{fesm2020 → fesm2022}/ctrl-ngx-emoji-mart-ngx-emoji.mjs +81 -68
  17. package/{fesm2020 → fesm2022}/ctrl-ngx-emoji-mart-ngx-emoji.mjs.map +1 -1
  18. package/{fesm2020 → fesm2022}/ctrl-ngx-emoji-mart.mjs +327 -261
  19. package/fesm2022/ctrl-ngx-emoji-mart.mjs.map +1 -0
  20. package/ngx-emoji/emoji.component.d.ts +10 -9
  21. package/ngx-emoji/emoji.module.d.ts +1 -2
  22. package/package.json +8 -16
  23. package/picker.component.d.ts +2 -2
  24. package/picker.module.d.ts +1 -4
  25. package/preview.component.d.ts +2 -2
  26. package/search.component.d.ts +1 -1
  27. package/skins.component.d.ts +2 -2
  28. package/esm2020/anchors.component.mjs +0 -83
  29. package/esm2020/category.component.mjs +0 -386
  30. package/esm2020/emoji-frequently.service.mjs +0 -88
  31. package/esm2020/emoji-search.service.mjs +0 -177
  32. package/esm2020/ngx-emoji/emoji.component.mjs +0 -283
  33. package/esm2020/ngx-emoji/emoji.module.mjs +0 -18
  34. package/esm2020/ngx-emoji/emoji.service.mjs +0 -144
  35. package/esm2020/picker.component.mjs +0 -508
  36. package/esm2020/picker.module.mjs +0 -49
  37. package/esm2020/preview.component.mjs +0 -187
  38. package/esm2020/search.component.mjs +0 -165
  39. package/esm2020/skins.component.mjs +0 -108
  40. package/fesm2015/ctrl-ngx-emoji-mart-ngx-emoji.mjs +0 -34325
  41. package/fesm2015/ctrl-ngx-emoji-mart-ngx-emoji.mjs.map +0 -1
  42. package/fesm2015/ctrl-ngx-emoji-mart.mjs +0 -1763
  43. package/fesm2015/ctrl-ngx-emoji-mart.mjs.map +0 -1
  44. package/fesm2020/ctrl-ngx-emoji-mart.mjs.map +0 -1
  45. /package/{esm2020 → esm2022}/ctrl-ngx-emoji-mart.mjs +0 -0
  46. /package/{esm2020 → esm2022}/ngx-emoji/ctrl-ngx-emoji-mart-ngx-emoji.mjs +0 -0
  47. /package/{esm2020 → esm2022}/ngx-emoji/data/categories.mjs +0 -0
  48. /package/{esm2020 → esm2022}/ngx-emoji/data/data.interfaces.mjs +0 -0
  49. /package/{esm2020 → esm2022}/ngx-emoji/data/emojis.mjs +0 -0
  50. /package/{esm2020 → esm2022}/ngx-emoji/data/skins.mjs +0 -0
  51. /package/{esm2020 → esm2022}/ngx-emoji/index.mjs +0 -0
  52. /package/{esm2020 → esm2022}/public_api.mjs +0 -0
  53. /package/{esm2020 → esm2022}/svgs/index.mjs +0 -0
  54. /package/{esm2020 → esm2022}/utils/index.mjs +0 -0
@@ -0,0 +1,409 @@
1
+ import { EmojiComponent } from '@ctrl/ngx-emoji-mart/ngx-emoji';
2
+ import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output, ViewChild, } from '@angular/core';
3
+ import { CommonModule } from '@angular/common';
4
+ import { Subject } from 'rxjs';
5
+ import * as i0 from "@angular/core";
6
+ import * as i1 from "@ctrl/ngx-emoji-mart/ngx-emoji";
7
+ import * as i2 from "./emoji-frequently.service";
8
+ import * as i3 from "@angular/common";
9
+ class CategoryComponent {
10
+ ref;
11
+ emojiService;
12
+ frequently;
13
+ emojis = null;
14
+ hasStickyPosition = true;
15
+ name = '';
16
+ perLine = 9;
17
+ totalFrequentLines = 4;
18
+ recent = [];
19
+ custom = [];
20
+ i18n;
21
+ id;
22
+ hideObsolete = true;
23
+ notFoundEmoji;
24
+ virtualize = false;
25
+ virtualizeOffset = 0;
26
+ emojiIsNative;
27
+ emojiSkin;
28
+ emojiSize;
29
+ emojiSet;
30
+ emojiSheetSize;
31
+ emojiForceSize;
32
+ emojiTooltip;
33
+ emojiBackgroundImageFn;
34
+ emojiImageUrlFn;
35
+ emojiUseButton;
36
+ emojiClick = new EventEmitter();
37
+ /**
38
+ * Note: the suffix is added explicitly so we know the event is dispatched outside of the Angular zone.
39
+ */
40
+ emojiOverOutsideAngular = new EventEmitter();
41
+ emojiLeaveOutsideAngular = new EventEmitter();
42
+ container;
43
+ label;
44
+ containerStyles = {};
45
+ emojisToDisplay = [];
46
+ filteredEmojisSubject = new Subject();
47
+ filteredEmojis$ = this.filteredEmojisSubject.asObservable();
48
+ labelStyles = {};
49
+ labelSpanStyles = {};
50
+ margin = 0;
51
+ minMargin = 0;
52
+ maxMargin = 0;
53
+ top = 0;
54
+ rows = 0;
55
+ constructor(ref, emojiService, frequently) {
56
+ this.ref = ref;
57
+ this.emojiService = emojiService;
58
+ this.frequently = frequently;
59
+ }
60
+ ngOnInit() {
61
+ this.updateRecentEmojis();
62
+ this.emojisToDisplay = this.filterEmojis();
63
+ if (this.noEmojiToDisplay) {
64
+ this.containerStyles = { display: 'none' };
65
+ }
66
+ if (!this.hasStickyPosition) {
67
+ this.labelStyles = { height: 28 };
68
+ // this.labelSpanStyles = { position: 'absolute' };
69
+ }
70
+ }
71
+ ngOnChanges(changes) {
72
+ if (changes.emojis?.currentValue?.length !== changes.emojis?.previousValue?.length) {
73
+ this.emojisToDisplay = this.filterEmojis();
74
+ this.ngAfterViewInit();
75
+ }
76
+ }
77
+ ngAfterViewInit() {
78
+ if (!this.virtualize) {
79
+ return;
80
+ }
81
+ const { width } = this.container.nativeElement.getBoundingClientRect();
82
+ const perRow = Math.floor(width / (this.emojiSize + 12));
83
+ this.rows = Math.ceil(this.emojisToDisplay.length / perRow);
84
+ this.containerStyles = {
85
+ ...this.containerStyles,
86
+ minHeight: `${this.rows * (this.emojiSize + 12) + 28}px`,
87
+ };
88
+ this.ref.detectChanges();
89
+ this.handleScroll(this.container.nativeElement.parentNode.parentNode.scrollTop);
90
+ }
91
+ get noEmojiToDisplay() {
92
+ return this.emojisToDisplay.length === 0;
93
+ }
94
+ memoizeSize() {
95
+ const parent = this.container.nativeElement.parentNode.parentNode;
96
+ const { top, height } = this.container.nativeElement.getBoundingClientRect();
97
+ const parentTop = parent.getBoundingClientRect().top;
98
+ const labelHeight = this.label.nativeElement.getBoundingClientRect().height;
99
+ this.top = top - parentTop + parent.scrollTop;
100
+ if (height === 0) {
101
+ this.maxMargin = 0;
102
+ }
103
+ else {
104
+ this.maxMargin = height - labelHeight;
105
+ }
106
+ }
107
+ handleScroll(scrollTop) {
108
+ let margin = scrollTop - this.top;
109
+ margin = margin < this.minMargin ? this.minMargin : margin;
110
+ margin = margin > this.maxMargin ? this.maxMargin : margin;
111
+ if (this.virtualize) {
112
+ const { top, height } = this.container.nativeElement.getBoundingClientRect();
113
+ const parentHeight = this.container.nativeElement.parentNode.parentNode.clientHeight;
114
+ if (parentHeight + (parentHeight + this.virtualizeOffset) >= top &&
115
+ -height - (parentHeight + this.virtualizeOffset) <= top) {
116
+ this.filteredEmojisSubject.next(this.emojisToDisplay);
117
+ }
118
+ else {
119
+ this.filteredEmojisSubject.next([]);
120
+ }
121
+ }
122
+ if (margin === this.margin) {
123
+ this.ref.detectChanges();
124
+ return false;
125
+ }
126
+ if (!this.hasStickyPosition) {
127
+ this.label.nativeElement.style.top = `${margin}px`;
128
+ }
129
+ this.margin = margin;
130
+ this.ref.detectChanges();
131
+ return true;
132
+ }
133
+ updateRecentEmojis() {
134
+ if (this.name !== 'Recent') {
135
+ return;
136
+ }
137
+ let frequentlyUsed = this.recent || this.frequently.get(this.perLine, this.totalFrequentLines);
138
+ if (!frequentlyUsed || !frequentlyUsed.length) {
139
+ frequentlyUsed = this.frequently.get(this.perLine, this.totalFrequentLines);
140
+ }
141
+ if (!frequentlyUsed.length) {
142
+ return;
143
+ }
144
+ this.emojis = frequentlyUsed
145
+ .map(id => {
146
+ const emoji = this.custom.filter((e) => e.id === id)[0];
147
+ if (emoji) {
148
+ return emoji;
149
+ }
150
+ return id;
151
+ })
152
+ .filter(id => !!this.emojiService.getData(id));
153
+ }
154
+ updateDisplay(display) {
155
+ this.containerStyles.display = display;
156
+ this.updateRecentEmojis();
157
+ this.ref.detectChanges();
158
+ }
159
+ trackById(index, item) {
160
+ return item;
161
+ }
162
+ filterEmojis() {
163
+ const newEmojis = [];
164
+ for (const emoji of this.emojis || []) {
165
+ if (!emoji) {
166
+ continue;
167
+ }
168
+ const data = this.emojiService.getData(emoji);
169
+ if (!data || (data.obsoletedBy && this.hideObsolete) || (!data.unified && !data.custom)) {
170
+ continue;
171
+ }
172
+ newEmojis.push(emoji);
173
+ }
174
+ return newEmojis;
175
+ }
176
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: CategoryComponent, deps: [{ token: i0.ChangeDetectorRef }, { token: i1.EmojiService }, { token: i2.EmojiFrequentlyService }], target: i0.ɵɵFactoryTarget.Component });
177
+ static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.0", type: CategoryComponent, isStandalone: true, selector: "emoji-category", inputs: { emojis: "emojis", hasStickyPosition: "hasStickyPosition", name: "name", perLine: "perLine", totalFrequentLines: "totalFrequentLines", recent: "recent", custom: "custom", i18n: "i18n", id: "id", hideObsolete: "hideObsolete", notFoundEmoji: "notFoundEmoji", virtualize: "virtualize", virtualizeOffset: "virtualizeOffset", emojiIsNative: "emojiIsNative", emojiSkin: "emojiSkin", emojiSize: "emojiSize", emojiSet: "emojiSet", emojiSheetSize: "emojiSheetSize", emojiForceSize: "emojiForceSize", emojiTooltip: "emojiTooltip", emojiBackgroundImageFn: "emojiBackgroundImageFn", emojiImageUrlFn: "emojiImageUrlFn", emojiUseButton: "emojiUseButton" }, outputs: { emojiClick: "emojiClick", emojiOverOutsideAngular: "emojiOverOutsideAngular", emojiLeaveOutsideAngular: "emojiLeaveOutsideAngular" }, viewQueries: [{ propertyName: "container", first: true, predicate: ["container"], descendants: true, static: true }, { propertyName: "label", first: true, predicate: ["label"], descendants: true, static: true }], usesOnChanges: true, ngImport: i0, template: `
178
+ <section
179
+ #container
180
+ class="emoji-mart-category"
181
+ [attr.aria-label]="i18n.categories[id]"
182
+ [class.emoji-mart-no-results]="noEmojiToDisplay"
183
+ [ngStyle]="containerStyles"
184
+ >
185
+ <div class="emoji-mart-category-label" [ngStyle]="labelStyles" [attr.data-name]="name">
186
+ <!-- already labeled by the section aria-label -->
187
+ <span #label [ngStyle]="labelSpanStyles" aria-hidden="true">
188
+ {{ i18n.categories[id] }}
189
+ </span>
190
+ </div>
191
+
192
+ <div *ngIf="virtualize; else normalRenderTemplate">
193
+ <div *ngIf="filteredEmojis$ | async as filteredEmojis">
194
+ <ngx-emoji
195
+ *ngFor="let emoji of filteredEmojis; trackBy: trackById"
196
+ [emoji]="emoji"
197
+ [size]="emojiSize"
198
+ [skin]="emojiSkin"
199
+ [isNative]="emojiIsNative"
200
+ [set]="emojiSet"
201
+ [sheetSize]="emojiSheetSize"
202
+ [forceSize]="emojiForceSize"
203
+ [tooltip]="emojiTooltip"
204
+ [backgroundImageFn]="emojiBackgroundImageFn"
205
+ [imageUrlFn]="emojiImageUrlFn"
206
+ [hideObsolete]="hideObsolete"
207
+ [useButton]="emojiUseButton"
208
+ (emojiOverOutsideAngular)="emojiOverOutsideAngular.emit($event)"
209
+ (emojiLeaveOutsideAngular)="emojiLeaveOutsideAngular.emit($event)"
210
+ (emojiClick)="emojiClick.emit($event)"
211
+ ></ngx-emoji>
212
+ </div>
213
+ </div>
214
+
215
+ <div *ngIf="noEmojiToDisplay">
216
+ <div>
217
+ <ngx-emoji
218
+ [emoji]="notFoundEmoji"
219
+ [size]="38"
220
+ [skin]="emojiSkin"
221
+ [isNative]="emojiIsNative"
222
+ [set]="emojiSet"
223
+ [sheetSize]="emojiSheetSize"
224
+ [forceSize]="emojiForceSize"
225
+ [tooltip]="emojiTooltip"
226
+ [backgroundImageFn]="emojiBackgroundImageFn"
227
+ [useButton]="emojiUseButton"
228
+ ></ngx-emoji>
229
+ </div>
230
+
231
+ <div class="emoji-mart-no-results-label">
232
+ {{ i18n.notfound }}
233
+ </div>
234
+ </div>
235
+ </section>
236
+
237
+ <ng-template #normalRenderTemplate>
238
+ <ngx-emoji
239
+ *ngFor="let emoji of emojisToDisplay; trackBy: trackById"
240
+ [emoji]="emoji"
241
+ [size]="emojiSize"
242
+ [skin]="emojiSkin"
243
+ [isNative]="emojiIsNative"
244
+ [set]="emojiSet"
245
+ [sheetSize]="emojiSheetSize"
246
+ [forceSize]="emojiForceSize"
247
+ [tooltip]="emojiTooltip"
248
+ [backgroundImageFn]="emojiBackgroundImageFn"
249
+ [imageUrlFn]="emojiImageUrlFn"
250
+ [hideObsolete]="hideObsolete"
251
+ [useButton]="emojiUseButton"
252
+ (emojiOverOutsideAngular)="emojiOverOutsideAngular.emit($event)"
253
+ (emojiLeaveOutsideAngular)="emojiLeaveOutsideAngular.emit($event)"
254
+ (emojiClick)="emojiClick.emit($event)"
255
+ ></ngx-emoji>
256
+ </ng-template>
257
+ `, isInline: true, dependencies: [{ kind: "ngmodule", type: CommonModule }, { kind: "directive", type: i3.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i3.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i3.NgStyle, selector: "[ngStyle]", inputs: ["ngStyle"] }, { kind: "pipe", type: i3.AsyncPipe, name: "async" }, { kind: "component", type: EmojiComponent, selector: "ngx-emoji", inputs: ["skin", "set", "sheetSize", "isNative", "forceSize", "tooltip", "size", "emoji", "fallback", "hideObsolete", "sheetRows", "sheetColumns", "useButton", "backgroundImageFn", "imageUrlFn"], outputs: ["emojiClick", "emojiOver", "emojiOverOutsideAngular", "emojiLeave", "emojiLeaveOutsideAngular"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
258
+ }
259
+ export { CategoryComponent };
260
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: CategoryComponent, decorators: [{
261
+ type: Component,
262
+ args: [{
263
+ selector: 'emoji-category',
264
+ template: `
265
+ <section
266
+ #container
267
+ class="emoji-mart-category"
268
+ [attr.aria-label]="i18n.categories[id]"
269
+ [class.emoji-mart-no-results]="noEmojiToDisplay"
270
+ [ngStyle]="containerStyles"
271
+ >
272
+ <div class="emoji-mart-category-label" [ngStyle]="labelStyles" [attr.data-name]="name">
273
+ <!-- already labeled by the section aria-label -->
274
+ <span #label [ngStyle]="labelSpanStyles" aria-hidden="true">
275
+ {{ i18n.categories[id] }}
276
+ </span>
277
+ </div>
278
+
279
+ <div *ngIf="virtualize; else normalRenderTemplate">
280
+ <div *ngIf="filteredEmojis$ | async as filteredEmojis">
281
+ <ngx-emoji
282
+ *ngFor="let emoji of filteredEmojis; trackBy: trackById"
283
+ [emoji]="emoji"
284
+ [size]="emojiSize"
285
+ [skin]="emojiSkin"
286
+ [isNative]="emojiIsNative"
287
+ [set]="emojiSet"
288
+ [sheetSize]="emojiSheetSize"
289
+ [forceSize]="emojiForceSize"
290
+ [tooltip]="emojiTooltip"
291
+ [backgroundImageFn]="emojiBackgroundImageFn"
292
+ [imageUrlFn]="emojiImageUrlFn"
293
+ [hideObsolete]="hideObsolete"
294
+ [useButton]="emojiUseButton"
295
+ (emojiOverOutsideAngular)="emojiOverOutsideAngular.emit($event)"
296
+ (emojiLeaveOutsideAngular)="emojiLeaveOutsideAngular.emit($event)"
297
+ (emojiClick)="emojiClick.emit($event)"
298
+ ></ngx-emoji>
299
+ </div>
300
+ </div>
301
+
302
+ <div *ngIf="noEmojiToDisplay">
303
+ <div>
304
+ <ngx-emoji
305
+ [emoji]="notFoundEmoji"
306
+ [size]="38"
307
+ [skin]="emojiSkin"
308
+ [isNative]="emojiIsNative"
309
+ [set]="emojiSet"
310
+ [sheetSize]="emojiSheetSize"
311
+ [forceSize]="emojiForceSize"
312
+ [tooltip]="emojiTooltip"
313
+ [backgroundImageFn]="emojiBackgroundImageFn"
314
+ [useButton]="emojiUseButton"
315
+ ></ngx-emoji>
316
+ </div>
317
+
318
+ <div class="emoji-mart-no-results-label">
319
+ {{ i18n.notfound }}
320
+ </div>
321
+ </div>
322
+ </section>
323
+
324
+ <ng-template #normalRenderTemplate>
325
+ <ngx-emoji
326
+ *ngFor="let emoji of emojisToDisplay; trackBy: trackById"
327
+ [emoji]="emoji"
328
+ [size]="emojiSize"
329
+ [skin]="emojiSkin"
330
+ [isNative]="emojiIsNative"
331
+ [set]="emojiSet"
332
+ [sheetSize]="emojiSheetSize"
333
+ [forceSize]="emojiForceSize"
334
+ [tooltip]="emojiTooltip"
335
+ [backgroundImageFn]="emojiBackgroundImageFn"
336
+ [imageUrlFn]="emojiImageUrlFn"
337
+ [hideObsolete]="hideObsolete"
338
+ [useButton]="emojiUseButton"
339
+ (emojiOverOutsideAngular)="emojiOverOutsideAngular.emit($event)"
340
+ (emojiLeaveOutsideAngular)="emojiLeaveOutsideAngular.emit($event)"
341
+ (emojiClick)="emojiClick.emit($event)"
342
+ ></ngx-emoji>
343
+ </ng-template>
344
+ `,
345
+ changeDetection: ChangeDetectionStrategy.OnPush,
346
+ preserveWhitespaces: false,
347
+ standalone: true,
348
+ imports: [CommonModule, EmojiComponent],
349
+ }]
350
+ }], ctorParameters: function () { return [{ type: i0.ChangeDetectorRef }, { type: i1.EmojiService }, { type: i2.EmojiFrequentlyService }]; }, propDecorators: { emojis: [{
351
+ type: Input
352
+ }], hasStickyPosition: [{
353
+ type: Input
354
+ }], name: [{
355
+ type: Input
356
+ }], perLine: [{
357
+ type: Input
358
+ }], totalFrequentLines: [{
359
+ type: Input
360
+ }], recent: [{
361
+ type: Input
362
+ }], custom: [{
363
+ type: Input
364
+ }], i18n: [{
365
+ type: Input
366
+ }], id: [{
367
+ type: Input
368
+ }], hideObsolete: [{
369
+ type: Input
370
+ }], notFoundEmoji: [{
371
+ type: Input
372
+ }], virtualize: [{
373
+ type: Input
374
+ }], virtualizeOffset: [{
375
+ type: Input
376
+ }], emojiIsNative: [{
377
+ type: Input
378
+ }], emojiSkin: [{
379
+ type: Input
380
+ }], emojiSize: [{
381
+ type: Input
382
+ }], emojiSet: [{
383
+ type: Input
384
+ }], emojiSheetSize: [{
385
+ type: Input
386
+ }], emojiForceSize: [{
387
+ type: Input
388
+ }], emojiTooltip: [{
389
+ type: Input
390
+ }], emojiBackgroundImageFn: [{
391
+ type: Input
392
+ }], emojiImageUrlFn: [{
393
+ type: Input
394
+ }], emojiUseButton: [{
395
+ type: Input
396
+ }], emojiClick: [{
397
+ type: Output
398
+ }], emojiOverOutsideAngular: [{
399
+ type: Output
400
+ }], emojiLeaveOutsideAngular: [{
401
+ type: Output
402
+ }], container: [{
403
+ type: ViewChild,
404
+ args: ['container', { static: true }]
405
+ }], label: [{
406
+ type: ViewChild,
407
+ args: ['label', { static: true }]
408
+ }] } });
409
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiY2F0ZWdvcnkuY29tcG9uZW50LmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9waWNrZXIvY2F0ZWdvcnkuY29tcG9uZW50LnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBUyxjQUFjLEVBQWdCLE1BQU0sZ0NBQWdDLENBQUM7QUFDckYsT0FBTyxFQUVMLHVCQUF1QixFQUV2QixTQUFTLEVBRVQsWUFBWSxFQUNaLEtBQUssRUFHTCxNQUFNLEVBRU4sU0FBUyxHQUNWLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFBRSxZQUFZLEVBQUUsTUFBTSxpQkFBaUIsQ0FBQztBQUMvQyxPQUFPLEVBQWMsT0FBTyxFQUFFLE1BQU0sTUFBTSxDQUFDOzs7OztBQUkzQyxNQXdGYSxpQkFBaUI7SUE2Q25CO0lBQ0M7SUFDQTtJQTlDRCxNQUFNLEdBQWlCLElBQUksQ0FBQztJQUM1QixpQkFBaUIsR0FBRyxJQUFJLENBQUM7SUFDekIsSUFBSSxHQUFHLEVBQUUsQ0FBQztJQUNWLE9BQU8sR0FBRyxDQUFDLENBQUM7SUFDWixrQkFBa0IsR0FBRyxDQUFDLENBQUM7SUFDdkIsTUFBTSxHQUFhLEVBQUUsQ0FBQztJQUN0QixNQUFNLEdBQVUsRUFBRSxDQUFDO0lBQ25CLElBQUksQ0FBTTtJQUNWLEVBQUUsQ0FBTTtJQUNSLFlBQVksR0FBRyxJQUFJLENBQUM7SUFDcEIsYUFBYSxDQUFVO0lBQ3ZCLFVBQVUsR0FBRyxLQUFLLENBQUM7SUFDbkIsZ0JBQWdCLEdBQUcsQ0FBQyxDQUFDO0lBQ3JCLGFBQWEsQ0FBcUI7SUFDbEMsU0FBUyxDQUFpQjtJQUMxQixTQUFTLENBQWlCO0lBQzFCLFFBQVEsQ0FBZ0I7SUFDeEIsY0FBYyxDQUFzQjtJQUNwQyxjQUFjLENBQXNCO0lBQ3BDLFlBQVksQ0FBb0I7SUFDaEMsc0JBQXNCLENBQThCO0lBQ3BELGVBQWUsQ0FBdUI7SUFDdEMsY0FBYyxDQUFXO0lBQ3hCLFVBQVUsR0FBd0Is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TUFBTTtzQkFBZCxLQUFLO2dCQUNHLElBQUk7c0JBQVosS0FBSztnQkFDRyxFQUFFO3NCQUFWLEtBQUs7Z0JBQ0csWUFBWTtzQkFBcEIsS0FBSztnQkFDRyxhQUFhO3NCQUFyQixLQUFLO2dCQUNHLFVBQVU7c0JBQWxCLEtBQUs7Z0JBQ0csZ0JBQWdCO3NCQUF4QixLQUFLO2dCQUNHLGFBQWE7c0JBQXJCLEtBQUs7Z0JBQ0csU0FBUztzQkFBakIsS0FBSztnQkFDRyxTQUFTO3NCQUFqQixLQUFLO2dCQUNHLFFBQVE7c0JBQWhCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDRyxjQUFjO3NCQUF0QixLQUFLO2dCQUNHLFlBQVk7c0JBQXBCLEtBQUs7Z0JBQ0csc0JBQXNCO3NCQUE5QixLQUFLO2dCQUNHLGVBQWU7c0JBQXZCLEtBQUs7Z0JBQ0csY0FBYztzQkFBdEIsS0FBSztnQkFDSSxVQUFVO3NCQUFuQixNQUFNO2dCQUlHLHVCQUF1QjtzQkFBaEMsTUFBTTtnQkFDRyx3QkFBd0I7c0JBQWpDLE1BQU07Z0JBQ21DLFNBQVM7c0JBQWxELFNBQVM7dUJBQUMsV0FBVyxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFDRixLQUFLO3NCQUExQyxTQUFTO3VCQUFDLE9BQU8sRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyJpbXBvcnQgeyBFbW9qaSwgRW1vamlDb21wb25lbnQsIEVtb2ppU2VydmljZSB9IGZyb20gJ0BjdHJsL25neC1lbW9qaS1tYXJ0L25neC1lbW9qaSc7XG5pbXBvcnQge1xuICBBZnRlclZpZXdJbml0LFxuICBDaGFuZ2VEZXRlY3Rpb25TdHJhdGVneSxcbiAgQ2hhbmdlRGV0ZWN0b3JSZWYsXG4gIENvbXBvbmVudCxcbiAgRWxlbWVudFJlZixcbiAgRXZlbnRFbWl0dGVyLFxuICBJbnB1dCxcbiAgT25DaGFuZ2VzLFxuICBPbkluaXQsXG4gIE91dHB1dCxcbiAgU2ltcGxlQ2hhbmdlcyxcbiAgVmlld0NoaWxkLFxufSBmcm9tICdAYW5ndWxhci9jb3JlJztcbmltcG9ydCB7IENvbW1vbk1vZHVsZSB9IGZyb20gJ0Bhbmd1bGFyL2NvbW1vbic7XG5pbXBvcnQgeyBPYnNlcnZhYmxlLCBTdWJqZWN0IH0gZnJvbSAncnhqcyc7XG5cbmltcG9ydCB7IEVtb2ppRnJlcXVlbnRseVNlcnZpY2UgfSBmcm9tICcuL2Vtb2ppLWZyZXF1ZW50bHkuc2VydmljZSc7XG5cbkBDb21wb25lbnQoe1xuICBzZWxlY3RvcjogJ2Vtb2ppLWNhdGVnb3J5JyxcbiAgdGVtcGxhdGU6IGBcbiAgICA8c2VjdGlvblxuICAgICAgI2NvbnRhaW5lclxuICAgICAgY2xhc3M9XCJlbW9qaS1tYXJ0LWNhdGVnb3J5XCJcbiAgICAgIFthdHRyLmFyaWEtbGFiZWxdPVwiaTE4bi5jYXRlZ29yaWVzW2lkXVwiXG4gICAgICBbY2xhc3MuZW1vamktbWFydC1uby1yZXN1bHRzXT1cIm5vRW1vamlUb0Rpc3BsYXlcIlxuICAgICAgW25nU3R5bGVdPVwiY29udGFpbmVyU3R5bGVzXCJcbiAgICA+XG4gICAgICA8ZGl2IGNsYXNzPVwiZW1vamktbWFydC1jYXRlZ29yeS1sYWJlbFwiIFtuZ1N0eWxlXT1cImxhYmVsU3R5bGVzXCIgW2F0dHIuZGF0YS1uYW1lXT1cIm5hbWVcIj5cbiAgICAgICAgPCEtLSBhbHJlYWR5IGxhYmVsZWQgYnkgdGhlIHNlY3Rpb24gYXJpYS1sYWJlbCAtLT5cbiAgICAgICAgPHNwYW4gI2xhYmVsIFtuZ1N0eWxlXT1cImxhYmVsU3BhblN0eWxlc1wiIGFyaWEtaGlkZGVuPVwidHJ1ZVwiPlxuICAgICAgICAgIHt7IGkxOG4uY2F0ZWdvcmllc1tpZF0gfX1cbiAgICAgICAgPC9zcGFuPlxuICAgICAgPC9kaXY+XG5cbiAgICAgIDxkaXYgKm5nSWY9XCJ2aXJ0dWFsaXplOyBlbHNlIG5vcm1hbFJlbmRlclRlbXBsYXRlXCI+XG4gICAgICAgIDxkaXYgKm5nSWY9XCJmaWx0ZXJlZEVtb2ppcyQgfCBhc3luYyBhcyBmaWx0ZXJlZEVtb2ppc1wiPlxuICAgICAgICAgIDxuZ3gtZW1vamlcbiAgICAgICAgICAgICpuZ0Zvcj1cImxldCBlbW9qaSBvZiBmaWx0ZXJlZEVtb2ppczsgdHJhY2tCeTogdHJhY2tCeUlkXCJcbiAgICAgICAgICAgIFtlbW9qaV09XCJlbW9qaVwiXG4gICAgICAgICAgICBbc2l6ZV09XCJlbW9qaVNpemVcIlxuICAgICAgICAgICAgW3NraW5dPVwiZW1vamlTa2luXCJcbiAgICAgICAgICAgIFtpc05hdGl2ZV09XCJlbW9qaUlzTmF0aXZlXCJcbiAgICAgICAgICAgIFtzZXRdPVwiZW1vamlTZXRcIlxuICAgICAgICAgICAgW3NoZWV0U2l6ZV09XCJlbW9qaVNoZWV0U2l6ZVwiXG4gICAgICAgICAgICBbZm9yY2VTaXplXT1cImVtb2ppRm9yY2VTaXplXCJcbiAgICAgICAgICAgIFt0b29sdGlwXT1cImVtb2ppVG9vbHRpcFwiXG4gICAgICAgICAgICBbYmFja2dyb3VuZEltYWdlRm5dPVwiZW1vamlCYWNrZ3JvdW5kSW1hZ2VGblwiXG4gICAgICAgICAgICBbaW1hZ2VVcmxGbl09XCJlbW9qaUltYWdlVXJsRm5cIlxuICAgICAgICAgICAgW2hpZGVPYnNvbGV0ZV09XCJoaWRlT2Jzb2xldGVcIlxuICAgICAgICAgICAgW3VzZUJ1dHRvbl09XCJlbW9qaVVzZUJ1dHRvblwiXG4gICAgICAgICAgICAoZW1vamlPdmVyT3V0c2lkZUFuZ3VsYXIpPVwiZW1vamlPdmVyT3V0c2lkZUFuZ3VsYXIuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgICAgIChlbW9qaUxlYXZlT3V0c2lkZUFuZ3VsYXIpPVwiZW1vamlMZWF2ZU91dHNpZGVBbmd1bGFyLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgICAoZW1vamlDbGljayk9XCJlbW9qaUNsaWNrLmVtaXQoJGV2ZW50KVwiXG4gICAgICAgICAgPjwvbmd4LWVtb2ppPlxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuXG4gICAgICA8ZGl2ICpuZ0lmPVwibm9FbW9qaVRvRGlzcGxheVwiPlxuICAgICAgICA8ZGl2PlxuICAgICAgICAgIDxuZ3gtZW1vamlcbiAgICAgICAgICAgIFtlbW9qaV09XCJub3RGb3VuZEVtb2ppXCJcbiAgICAgICAgICAgIFtzaXplXT1cIjM4XCJcbiAgICAgICAgICAgIFtza2luXT1cImVtb2ppU2tpblwiXG4gICAgICAgICAgICBbaXNOYXRpdmVdPVwiZW1vamlJc05hdGl2ZVwiXG4gICAgICAgICAgICBbc2V0XT1cImVtb2ppU2V0XCJcbiAgICAgICAgICAgIFtzaGVldFNpemVdPVwiZW1vamlTaGVldFNpemVcIlxuICAgICAgICAgICAgW2ZvcmNlU2l6ZV09XCJlbW9qaUZvcmNlU2l6ZVwiXG4gICAgICAgICAgICBbdG9vbHRpcF09XCJlbW9qaVRvb2x0aXBcIlxuICAgICAgICAgICAgW2JhY2tncm91bmRJbWFnZUZuXT1cImVtb2ppQmFja2dyb3VuZEltYWdlRm5cIlxuICAgICAgICAgICAgW3VzZUJ1dHRvbl09XCJlbW9qaVVzZUJ1dHRvblwiXG4gICAgICAgICAgPjwvbmd4LWVtb2ppPlxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8ZGl2IGNsYXNzPVwiZW1vamktbWFydC1uby1yZXN1bHRzLWxhYmVsXCI+XG4gICAgICAgICAge3sgaTE4bi5ub3Rmb3VuZCB9fVxuICAgICAgICA8L2Rpdj5cbiAgICAgIDwvZGl2PlxuICAgIDwvc2VjdGlvbj5cblxuICAgIDxuZy10ZW1wbGF0ZSAjbm9ybWFsUmVuZGVyVGVtcGxhdGU+XG4gICAgICA8bmd4LWVtb2ppXG4gICAgICAgICpuZ0Zvcj1cImxldCBlbW9qaSBvZiBlbW9qaXNUb0Rpc3BsYXk7IHRyYWNrQnk6IHRyYWNrQnlJZFwiXG4gICAgICAgIFtlbW9qaV09XCJlbW9qaVwiXG4gICAgICAgIFtzaXplXT1cImVtb2ppU2l6ZVwiXG4gICAgICAgIFtza2luXT1cImVtb2ppU2tpblwiXG4gICAgICAgIFtpc05hdGl2ZV09XCJlbW9qaUlzTmF0aXZlXCJcbiAgICAgICAgW3NldF09XCJlbW9qaVNldFwiXG4gICAgICAgIFtzaGVldFNpemVdPVwiZW1vamlTaGVldFNpemVcIlxuICAgICAgICBbZm9yY2VTaXplXT1cImVtb2ppRm9yY2VTaXplXCJcbiAgICAgICAgW3Rvb2x0aXBdPVwiZW1vamlUb29sdGlwXCJcbiAgICAgICAgW2JhY2tncm91bmRJbWFnZUZuXT1cImVtb2ppQmFja2dyb3VuZEltYWdlRm5cIlxuICAgICAgICBbaW1hZ2VVcmxGbl09XCJlbW9qaUltYWdlVXJsRm5cIlxuICAgICAgICBbaGlkZU9ic29sZXRlXT1cImhpZGVPYnNvbGV0ZVwiXG4gICAgICAgIFt1c2VCdXR0b25dPVwiZW1vamlVc2VCdXR0b25cIlxuICAgICAgICAoZW1vamlPdmVyT3V0c2lkZUFuZ3VsYXIpPVwiZW1vamlPdmVyT3V0c2lkZUFuZ3VsYXIuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgKGVtb2ppTGVhdmVPdXRzaWRlQW5ndWxhcik9XCJlbW9qaUxlYXZlT3V0c2lkZUFuZ3VsYXIuZW1pdCgkZXZlbnQpXCJcbiAgICAgICAgKGVtb2ppQ2xpY2spPVwiZW1vamlDbGljay5lbWl0KCRldmVudClcIlxuICAgICAgPjwvbmd4LWVtb2ppPlxuICAgIDwvbmctdGVtcGxhdGU+XG4gIGAsXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoLFxuICBwcmVzZXJ2ZVdoaXRlc3BhY2VzOiBmYWxzZSxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW0NvbW1vbk1vZHVsZSwgRW1vamlDb21wb25lbnRdLFxufSlcbmV4cG9ydCBjbGFzcyBDYXRlZ29yeUNvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlcywgT25Jbml0LCBBZnRlclZpZXdJbml0IHtcbiAgQElucHV0KCkgZW1vamlzOiBhbnlbXSB8IG51bGwgPSBudWxsO1xuICBASW5wdXQoKSBoYXNTdGlja3lQb3NpdGlvbiA9IHRydWU7XG4gIEBJbnB1dCgpIG5hbWUgPSAnJztcbiAgQElucHV0KCkgcGVyTGluZSA9IDk7XG4gIEBJbnB1dCgpIHRvdGFsRnJlcXVlbnRMaW5lcyA9IDQ7XG4gIEBJbnB1dCgpIHJlY2VudDogc3RyaW5nW10gPSBbXTtcbiAgQElucHV0KCkgY3VzdG9tOiBhbnlbXSA9IFtdO1xuICBASW5wdXQoKSBpMThuOiBhbnk7XG4gIEBJbnB1dCgpIGlkOiBhbnk7XG4gIEBJbnB1dCgpIGhpZGVPYnNvbGV0ZSA9IHRydWU7XG4gIEBJbnB1dCgpIG5vdEZvdW5kRW1vamk/OiBzdHJpbmc7XG4gIEBJbnB1dCgpIHZpcnR1YWxpemUgPSBmYWxzZTtcbiAgQElucHV0KCkgdmlydHVhbGl6ZU9mZnNldCA9IDA7XG4gIEBJbnB1dCgpIGVtb2ppSXNOYXRpdmU/OiBFbW9qaVsnaXNOYXRpdmUnXTtcbiAgQElucHV0KCkgZW1vamlTa2luITogRW1vamlbJ3NraW4nXTtcbiAgQElucHV0KCkgZW1vamlTaXplITogRW1vamlbJ3NpemUnXTtcbiAgQElucHV0KCkgZW1vamlTZXQhOiBFbW9qaVsnc2V0J107XG4gIEBJbnB1dCgpIGVtb2ppU2hlZXRTaXplITogRW1vamlbJ3NoZWV0U2l6ZSddO1xuICBASW5wdXQoKSBlbW9qaUZvcmNlU2l6ZSE6IEVtb2ppWydmb3JjZVNpemUnXTtcbiAgQElucHV0KCkgZW1vamlUb29sdGlwITogRW1vamlbJ3Rvb2x0aXAnXTtcbiAgQElucHV0KCkgZW1vamlCYWNrZ3JvdW5kSW1hZ2VGbj86IEVtb2ppWydiYWNrZ3JvdW5kSW1hZ2VGbiddO1xuICBASW5wdXQoKSBlbW9qaUltYWdlVXJsRm4/OiBFbW9qaVsnaW1hZ2VVcmxGbiddO1xuICBASW5wdXQoKSBlbW9qaVVzZUJ1dHRvbj86IGJvb2xlYW47XG4gIEBPdXRwdXQoKSBlbW9qaUNsaWNrOiBFbW9qaVsnZW1vamlDbGljayddID0gbmV3IEV2ZW50RW1pdHRlcigpO1xuICAvKipcbiAgICogTm90ZTogdGhlIHN1ZmZpeCBpcyBhZGRlZCBleHBsaWNpdGx5IHNvIHdlIGtub3cgdGhlIGV2ZW50IGlzIGRpc3BhdGNoZWQgb3V0c2lkZSBvZiB0aGUgQW5ndWxhciB6b25lLlxuICAgKi9cbiAgQE91dHB1dCgpIGVtb2ppT3Zlck91dHNpZGVBbmd1bGFyOiBFbW9qaVsnZW1vamlPdmVyJ10gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBPdXRwdXQoKSBlbW9qaUxlYXZlT3V0c2lkZUFuZ3VsYXI6IEVtb2ppWydlbW9qaUxlYXZlJ10gPSBuZXcgRXZlbnRFbWl0dGVyKCk7XG4gIEBWaWV3Q2hpbGQoJ2NvbnRhaW5lcicsIHsgc3RhdGljOiB0cnVlIH0pIGNvbnRhaW5lciE6IEVsZW1lbnRSZWY7XG4gIEBWaWV3Q2hpbGQoJ2xhYmVsJywgeyBzdGF0aWM6IHRydWUgfSkgbGFiZWwhOiBFbGVtZW50UmVmO1xuICBjb250YWluZXJTdHlsZXM6IGFueSA9IHt9O1xuICBlbW9qaXNUb0Rpc3BsYXk6IGFueVtdID0gW107XG4gIHByaXZhdGUgZmlsdGVyZWRFbW9qaXNTdWJqZWN0ID0gbmV3IFN1YmplY3Q8YW55W10gfCBudWxsIHwgdW5kZWZpbmVkPigpO1xuICBmaWx0ZXJlZEVtb2ppcyQ6IE9ic2VydmFibGU8YW55W10gfCBudWxsIHwgdW5kZWZpbmVkPiA9IHRoaXMuZmlsdGVyZWRFbW9qaXNTdWJqZWN0LmFzT2JzZXJ2YWJsZSgpO1xuICBsYWJlbFN0eWxlczogYW55ID0ge307XG4gIGxhYmVsU3BhblN0eWxlczogYW55ID0ge307XG4gIG1hcmdpbiA9IDA7XG4gIG1pbk1hcmdpbiA9IDA7XG4gIG1heE1hcmdpbiA9IDA7XG4gIHRvcCA9IDA7XG4gIHJvd3MgPSAwO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIHB1YmxpYyByZWY6IENoYW5nZURldGVjdG9yUmVmLFxuICAgIHByaXZhdGUgZW1vamlTZXJ2aWNlOiBFbW9qaVNlcnZpY2UsXG4gICAgcHJpdmF0ZSBmcmVxdWVudGx5OiBFbW9qaUZyZXF1ZW50bHlTZXJ2aWNlLFxuICApIHt9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgdGhpcy51cGRhdGVSZWNlbnRFbW9qaXMoKTtcbiAgICB0aGlzLmVtb2ppc1RvRGlzcGxheSA9IHRoaXMuZmlsdGVyRW1vamlzKCk7XG5cbiAgICBpZiAodGhpcy5ub0Vtb2ppVG9EaXNwbGF5KSB7XG4gICAgICB0aGlzLmNvbnRhaW5lclN0eWxlcyA9IHsgZGlzcGxheTogJ25vbmUnIH07XG4gICAgfVxuXG4gICAgaWYgKCF0aGlzLmhhc1N0aWNreVBvc2l0aW9uKSB7XG4gICAgICB0aGlzLmxhYmVsU3R5bGVzID0geyBoZWlnaHQ6IDI4IH07XG4gICAgICAvLyB0aGlzLmxhYmVsU3BhblN0eWxlcyA9IHsgcG9zaXRpb246ICdhYnNvbHV0ZScgfTtcbiAgICB9XG4gIH1cblxuICBuZ09uQ2hhbmdlcyhjaGFuZ2VzOiBTaW1wbGVDaGFuZ2VzKSB7XG4gICAgaWYgKGNoYW5nZXMuZW1vamlzPy5jdXJyZW50VmFsdWU/Lmxlbmd0aCAhPT0gY2hhbmdlcy5lbW9qaXM/LnByZXZpb3VzVmFsdWU/Lmxlbmd0aCkge1xuICAgICAgdGhpcy5lbW9qaXNUb0Rpc3BsYXkgPSB0aGlzLmZpbHRlckVtb2ppcygpO1xuICAgICAgdGhpcy5uZ0FmdGVyVmlld0luaXQoKTtcbiAgICB9XG4gIH1cblxuICBuZ0FmdGVyVmlld0luaXQoKSB7XG4gICAgaWYgKCF0aGlzLnZpcnR1YWxpemUpIHtcbiAgICAgIHJldHVybjtcbiAgICB9XG5cbiAgICBjb25zdCB7IHdpZHRoIH0gPSB0aGlzLmNvbnRhaW5lci5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpO1xuXG4gICAgY29uc3QgcGVyUm93ID0gTWF0aC5mbG9vcih3aWR0aCAvICh0aGlzLmVtb2ppU2l6ZSArIDEyKSk7XG4gICAgdGhpcy5yb3dzID0gTWF0aC5jZWlsKHRoaXMuZW1vamlzVG9EaXNwbGF5Lmxlbmd0aCAvIHBlclJvdyk7XG5cbiAgICB0aGlzLmNvbnRhaW5lclN0eWxlcyA9IHtcbiAgICAgIC4uLnRoaXMuY29udGFpbmVyU3R5bGVzLFxuICAgICAgbWluSGVpZ2h0OiBgJHt0aGlzLnJvd3MgKiAodGhpcy5lbW9qaVNpemUgKyAxMikgKyAyOH1weGAsXG4gICAgfTtcblxuICAgIHRoaXMucmVmLmRldGVjdENoYW5nZXMoKTtcblxuICAgIHRoaXMuaGFuZGxlU2Nyb2xsKHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlLnNjcm9sbFRvcCk7XG4gIH1cblxuICBnZXQgbm9FbW9qaVRvRGlzcGxheSgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gdGhpcy5lbW9qaXNUb0Rpc3BsYXkubGVuZ3RoID09PSAwO1xuICB9XG5cbiAgbWVtb2l6ZVNpemUoKSB7XG4gICAgY29uc3QgcGFyZW50ID0gdGhpcy5jb250YWluZXIubmF0aXZlRWxlbWVudC5wYXJlbnROb2RlLnBhcmVudE5vZGU7XG4gICAgY29uc3QgeyB0b3AsIGhlaWdodCB9ID0gdGhpcy5jb250YWluZXIubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICBjb25zdCBwYXJlbnRUb3AgPSBwYXJlbnQuZ2V0Qm91bmRpbmdDbGllbnRSZWN0KCkudG9wO1xuICAgIGNvbnN0IGxhYmVsSGVpZ2h0ID0gdGhpcy5sYWJlbC5uYXRpdmVFbGVtZW50LmdldEJvdW5kaW5nQ2xpZW50UmVjdCgpLmhlaWdodDtcblxuICAgIHRoaXMudG9wID0gdG9wIC0gcGFyZW50VG9wICsgcGFyZW50LnNjcm9sbFRvcDtcblxuICAgIGlmIChoZWlnaHQgPT09IDApIHtcbiAgICAgIHRoaXMubWF4TWFyZ2luID0gMDtcbiAgICB9IGVsc2Uge1xuICAgICAgdGhpcy5tYXhNYXJnaW4gPSBoZWlnaHQgLSBsYWJlbEhlaWdodDtcbiAgICB9XG4gIH1cblxuICBoYW5kbGVTY3JvbGwoc2Nyb2xsVG9wOiBudW1iZXIpOiBib29sZWFuIHtcbiAgICBsZXQgbWFyZ2luID0gc2Nyb2xsVG9wIC0gdGhpcy50b3A7XG4gICAgbWFyZ2luID0gbWFyZ2luIDwgdGhpcy5taW5NYXJnaW4gPyB0aGlzLm1pbk1hcmdpbiA6IG1hcmdpbjtcbiAgICBtYXJnaW4gPSBtYXJnaW4gPiB0aGlzLm1heE1hcmdpbiA/IHRoaXMubWF4TWFyZ2luIDogbWFyZ2luO1xuXG4gICAgaWYgKHRoaXMudmlydHVhbGl6ZSkge1xuICAgICAgY29uc3QgeyB0b3AsIGhlaWdodCB9ID0gdGhpcy5jb250YWluZXIubmF0aXZlRWxlbWVudC5nZXRCb3VuZGluZ0NsaWVudFJlY3QoKTtcbiAgICAgIGNvbnN0IHBhcmVudEhlaWdodCA9IHRoaXMuY29udGFpbmVyLm5hdGl2ZUVsZW1lbnQucGFyZW50Tm9kZS5wYXJlbnROb2RlLmNsaWVudEhlaWdodDtcblxuICAgICAgaWYgKFxuICAgICAgICBwYXJlbnRIZWlnaHQgKyAocGFyZW50SGVpZ2h0ICsgdGhpcy52aXJ0dWFsaXplT2Zmc2V0KSA+PSB0b3AgJiZcbiAgICAgICAgLWhlaWdodCAtIChwYXJlbnRIZWlnaHQgKyB0aGlzLnZpcnR1YWxpemVPZmZzZXQpIDw9IHRvcFxuICAgICAgKSB7XG4gICAgICAgIHRoaXMuZmlsdGVyZWRFbW9qaXNTdWJqZWN0Lm5leHQodGhpcy5lbW9qaXNUb0Rpc3BsYXkpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5maWx0ZXJlZEVtb2ppc1N1YmplY3QubmV4dChbXSk7XG4gICAgICB9XG4gICAgfVxuXG4gICAgaWYgKG1hcmdpbiA9PT0gdGhpcy5tYXJnaW4pIHtcbiAgICAgIHRoaXMucmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9XG5cbiAgICBpZiAoIXRoaXMuaGFzU3RpY2t5UG9zaXRpb24pIHtcbiAgICAgIHRoaXMubGFiZWwubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSBgJHttYXJnaW59cHhgO1xuICAgIH1cblxuICAgIHRoaXMubWFyZ2luID0gbWFyZ2luO1xuICAgIHRoaXMucmVmLmRldGVjdENoYW5nZXMoKTtcbiAgICByZXR1cm4gdHJ1ZTtcbiAgfVxuXG4gIHVwZGF0ZVJlY2VudEVtb2ppcygpIHtcbiAgICBpZiAodGhpcy5uYW1lICE9PSAnUmVjZW50Jykge1xuICAgICAgcmV0dXJuO1xuICAgIH1cblxuICAgIGxldCBmcmVxdWVudGx5VXNlZCA9IHRoaXMucmVjZW50IHx8IHRoaXMuZnJlcXVlbnRseS5nZXQodGhpcy5wZXJMaW5lLCB0aGlzLnRvdGFsRnJlcXVlbnRMaW5lcyk7XG4gICAgaWYgKCFmcmVxdWVudGx5VXNlZCB8fCAhZnJlcXVlbnRseVVzZWQubGVuZ3RoKSB7XG4gICAgICBmcmVxdWVudGx5VXNlZCA9IHRoaXMuZnJlcXVlbnRseS5nZXQodGhpcy5wZXJMaW5lLCB0aGlzLnRvdGFsRnJlcXVlbnRMaW5lcyk7XG4gICAgfVxuICAgIGlmICghZnJlcXVlbnRseVVzZWQubGVuZ3RoKSB7XG4gICAgICByZXR1cm47XG4gICAgfVxuICAgIHRoaXMuZW1vamlzID0gZnJlcXVlbnRseVVzZWRcbiAgICAgIC5tYXAoaWQgPT4ge1xuICAgICAgICBjb25zdCBlbW9qaSA9IHRoaXMuY3VzdG9tLmZpbHRlcigoZTogYW55KSA9PiBlLmlkID09PSBpZClbMF07XG4gICAgICAgIGlmIChlbW9qaSkge1xuICAgICAgICAgIHJldHVybiBlbW9qaTtcbiAgICAgICAgfVxuXG4gICAgICAgIHJldHVybiBpZDtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKGlkID0+ICEhdGhpcy5lbW9qaVNlcnZpY2UuZ2V0RGF0YShpZCkpO1xuICB9XG5cbiAgdXBkYXRlRGlzcGxheShkaXNwbGF5OiAnbm9uZScgfCAnYmxvY2snKSB7XG4gICAgdGhpcy5jb250YWluZXJTdHlsZXMuZGlzcGxheSA9IGRpc3BsYXk7XG4gICAgdGhpcy51cGRhdGVSZWNlbnRFbW9qaXMoKTtcbiAgICB0aGlzLnJlZi5kZXRlY3RDaGFuZ2VzKCk7XG4gIH1cblxuICB0cmFja0J5SWQoaW5kZXg6IG51bWJlciwgaXRlbTogYW55KSB7XG4gICAgcmV0dXJuIGl0ZW07XG4gIH1cblxuICBwcml2YXRlIGZpbHRlckVtb2ppcygpOiBhbnlbXSB7XG4gICAgY29uc3QgbmV3RW1vamlzID0gW107XG4gICAgZm9yIChjb25zdCBlbW9qaSBvZiB0aGlzLmVtb2ppcyB8fCBbXSkge1xuICAgICAgaWYgKCFlbW9qaSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIGNvbnN0IGRhdGEgPSB0aGlzLmVtb2ppU2VydmljZS5nZXREYXRhKGVtb2ppKTtcbiAgICAgIGlmICghZGF0YSB8fCAoZGF0YS5vYnNvbGV0ZWRCeSAmJiB0aGlzLmhpZGVPYnNvbGV0ZSkgfHwgKCFkYXRhLnVuaWZpZWQgJiYgIWRhdGEuY3VzdG9tKSkge1xuICAgICAgICBjb250aW51ZTtcbiAgICAgIH1cbiAgICAgIG5ld0Vtb2ppcy5wdXNoKGVtb2ppKTtcbiAgICB9XG4gICAgcmV0dXJuIG5ld0Vtb2ppcztcbiAgfVxufVxuIl19
@@ -0,0 +1,90 @@
1
+ import { isPlatformBrowser } from '@angular/common';
2
+ import { Inject, Injectable, PLATFORM_ID } from '@angular/core';
3
+ import * as i0 from "@angular/core";
4
+ class EmojiFrequentlyService {
5
+ platformId;
6
+ NAMESPACE = 'emoji-mart';
7
+ frequently = null;
8
+ defaults = {};
9
+ initialized = false;
10
+ DEFAULTS = [
11
+ '+1',
12
+ 'grinning',
13
+ 'kissing_heart',
14
+ 'heart_eyes',
15
+ 'laughing',
16
+ 'stuck_out_tongue_winking_eye',
17
+ 'sweat_smile',
18
+ 'joy',
19
+ 'scream',
20
+ 'disappointed',
21
+ 'unamused',
22
+ 'weary',
23
+ 'sob',
24
+ 'sunglasses',
25
+ 'heart',
26
+ 'poop',
27
+ ];
28
+ constructor(platformId) {
29
+ this.platformId = platformId;
30
+ }
31
+ init() {
32
+ this.frequently = JSON.parse((isPlatformBrowser(this.platformId) &&
33
+ localStorage.getItem(`${this.NAMESPACE}.frequently`)) ||
34
+ 'null');
35
+ this.initialized = true;
36
+ }
37
+ add(emoji) {
38
+ if (!this.initialized) {
39
+ this.init();
40
+ }
41
+ if (!this.frequently) {
42
+ this.frequently = this.defaults;
43
+ }
44
+ if (!this.frequently[emoji.id]) {
45
+ this.frequently[emoji.id] = 0;
46
+ }
47
+ this.frequently[emoji.id] += 1;
48
+ if (isPlatformBrowser(this.platformId)) {
49
+ localStorage.setItem(`${this.NAMESPACE}.last`, emoji.id);
50
+ localStorage.setItem(`${this.NAMESPACE}.frequently`, JSON.stringify(this.frequently));
51
+ }
52
+ }
53
+ get(perLine, totalLines) {
54
+ if (!this.initialized) {
55
+ this.init();
56
+ }
57
+ if (this.frequently === null) {
58
+ this.defaults = {};
59
+ const result = [];
60
+ for (let i = 0; i < perLine; i++) {
61
+ this.defaults[this.DEFAULTS[i]] = perLine - i;
62
+ result.push(this.DEFAULTS[i]);
63
+ }
64
+ return result;
65
+ }
66
+ const quantity = perLine * totalLines;
67
+ const frequentlyKeys = Object.keys(this.frequently);
68
+ const sorted = frequentlyKeys
69
+ .sort((a, b) => this.frequently[a] - this.frequently[b])
70
+ .reverse();
71
+ const sliced = sorted.slice(0, quantity);
72
+ const last = isPlatformBrowser(this.platformId) && localStorage.getItem(`${this.NAMESPACE}.last`);
73
+ if (last && !sliced.includes(last)) {
74
+ sliced.pop();
75
+ sliced.push(last);
76
+ }
77
+ return sliced;
78
+ }
79
+ static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: EmojiFrequentlyService, deps: [{ token: PLATFORM_ID }], target: i0.ɵɵFactoryTarget.Injectable });
80
+ static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: EmojiFrequentlyService, providedIn: 'root' });
81
+ }
82
+ export { EmojiFrequentlyService };
83
+ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.0", ngImport: i0, type: EmojiFrequentlyService, decorators: [{
84
+ type: Injectable,
85
+ args: [{ providedIn: 'root' }]
86
+ }], ctorParameters: function () { return [{ type: undefined, decorators: [{
87
+ type: Inject,
88
+ args: [PLATFORM_ID]
89
+ }] }]; } });
90
+ //# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiZW1vamktZnJlcXVlbnRseS5zZXJ2aWNlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vc3JjL2xpYi9waWNrZXIvZW1vamktZnJlcXVlbnRseS5zZXJ2aWNlLnRzIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxNQUFNLEVBQUUsVUFBVSxFQUFFLFdBQVcsRUFBRSxNQUFNLGVBQWUsQ0FBQzs7QUFJaEUsTUFDYSxzQkFBc0I7SUF1QlE7SUF0QnpDLFNBQVMsR0FBRyxZQUFZLENBQUM7SUFDekIsVUFBVSxHQUFxQyxJQUFJLENBQUM7SUFDcEQsUUFBUSxHQUE4QixFQUFFLENBQUM7SUFDekMsV0FBVyxHQUFHLEtBQUssQ0FBQztJQUNwQixRQUFRLEdBQUc7UUFDVCxJQUFJO1FBQ0osVUFBVTtRQUNWLGVBQWU7UUFDZixZQUFZO1FBQ1osVUFBVTtRQUNWLDhCQUE4QjtRQUM5QixhQUFhO1FBQ2IsS0FBSztRQUNMLFFBQVE7UUFDUixjQUFjO1FBQ2QsVUFBVTtRQUNWLE9BQU87UUFDUCxLQUFLO1FBQ0wsWUFBWTtRQUNaLE9BQU87UUFDUCxNQUFNO0tBQ1AsQ0FBQztJQUNGLFlBQXlDLFVBQWtCO1FBQWxCLGVBQVUsR0FBVixVQUFVLENBQVE7SUFBRyxDQUFDO0lBQy9ELElBQUk7UUFDRixJQUFJLENBQUMsVUFBVSxHQUFHLElBQUksQ0FBQyxLQUFLLENBQzFCLENBQUMsaUJBQWlCLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQztZQUNqQyxZQUFZLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsYUFBYSxDQUFDLENBQUM7WUFDckQsTUFBTSxDQUNULENBQUM7UUFDRixJQUFJLENBQUMsV0FBVyxHQUFHLElBQUksQ0FBQztJQUMxQixDQUFDO0lBQ0QsR0FBRyxDQUFDLEtBQWdCO1FBQ2xCLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFO1lBQ3JCLElBQUksQ0FBQyxJQUFJLEVBQUUsQ0FBQztTQUNiO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLEVBQUU7WUFDcEIsSUFBSSxDQUFDLFVBQVUsR0FBRyxJQUFJLENBQUMsUUFBUSxDQUFDO1NBQ2pDO1FBQ0QsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxFQUFFO1lBQzlCLElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxHQUFHLENBQUMsQ0FBQztTQUMvQjtRQUNELElBQUksQ0FBQyxVQUFVLENBQUMsS0FBSyxDQUFDLEVBQUUsQ0FBQyxJQUFJLENBQUMsQ0FBQztRQUUvQixJQUFJLGlCQUFpQixDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRTtZQUN0QyxZQUFZLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsT0FBTyxFQUFFLEtBQUssQ0FBQyxFQUFFLENBQUMsQ0FBQztZQUN6RCxZQUFZLENBQUMsT0FBTyxDQUFDLEdBQUcsSUFBSSxDQUFDLFNBQVMsYUFBYSxFQUFFLElBQUksQ0FBQyxTQUFTLENBQUMsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUM7U0FDdkY7SUFDSCxDQUFDO0lBQ0QsR0FBRyxDQUFDLE9BQWUsRUFBRSxVQUFrQjtRQUNyQyxJQUFJLENBQUMsSUFBSSxDQUFDLFdBQVcsRUFBRTtZQUNyQixJQUFJLENBQUMsSUFBSSxFQUFFLENBQUM7U0FDYjtRQUNELElBQUksSUFBSSxDQUFDLFVBQVUsS0FBSyxJQUFJLEVBQUU7WUFDNUIsSUFBSSxDQUFDLFFBQVEsR0FBRyxFQUFFLENBQUM7WUFDbkIsTUFBTSxNQUFNLEdBQUcsRUFBRSxDQUFDO1lBRWxCLEtBQUssSUFBSSxDQUFDLEdBQUcsQ0FBQyxFQUFFLENBQUMsR0FBRyxPQUFPLEVBQUUsQ0FBQyxFQUFFLEVBQUU7Z0JBQ2hDLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxHQUFHLE9BQU8sR0FBRyxDQUFDLENBQUM7Z0JBQzlDLE1BQU0sQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxDQUFDLENBQUMsQ0FBQyxDQUFDO2FBQy9CO1lBQ0QsT0FBTyxNQUFNLENBQUM7U0FDZjtRQUVELE1BQU0sUUFBUSxHQUFHLE9BQU8sR0FBRyxVQUFVLENBQUM7UUFDdEMsTUFBTSxjQUFjLEdBQUcsTUFBTSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLENBQUM7UUFFcEQsTUFBTSxNQUFNLEdBQUcsY0FBYzthQUMxQixJQUFJLENBQUMsQ0FBQyxDQUFDLEVBQUUsQ0FBQyxFQUFFLEVBQUUsQ0FBQyxJQUFJLENBQUMsVUFBVyxDQUFDLENBQUMsQ0FBQyxHQUFHLElBQUksQ0FBQyxVQUFXLENBQUMsQ0FBQyxDQUFDLENBQUM7YUFDekQsT0FBTyxFQUFFLENBQUM7UUFDYixNQUFNLE1BQU0sR0FBRyxNQUFNLENBQUMsS0FBSyxDQUFDLENBQUMsRUFBRSxRQUFRLENBQUMsQ0FBQztRQUV6QyxNQUFNLElBQUksR0FDUixpQkFBaUIsQ0FBQyxJQUFJLENBQUMsVUFBVSxDQUFDLElBQUksWUFBWSxDQUFDLE9BQU8sQ0FBQyxHQUFHLElBQUksQ0FBQyxTQUFTLE9BQU8sQ0FBQyxDQUFDO1FBRXZGLElBQUksSUFBSSxJQUFJLENBQUMsTUFBTSxDQUFDLFFBQVEsQ0FBQyxJQUFJLENBQUMsRUFBRTtZQUNsQyxNQUFNLENBQUMsR0FBRyxFQUFFLENBQUM7WUFDYixNQUFNLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1NBQ25CO1FBQ0QsT0FBTyxNQUFNLENBQUM7SUFDaEIsQ0FBQzt1R0FoRlUsc0JBQXNCLGtCQXVCYixXQUFXOzJHQXZCcEIsc0JBQXNCLGNBRFQsTUFBTTs7U0FDbkIsc0JBQXNCOzJGQUF0QixzQkFBc0I7a0JBRGxDLFVBQVU7bUJBQUMsRUFBRSxVQUFVLEVBQUUsTUFBTSxFQUFFOzswQkF3Qm5CLE1BQU07MkJBQUMsV0FBVyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IGlzUGxhdGZvcm1Ccm93c2VyIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IEluamVjdCwgSW5qZWN0YWJsZSwgUExBVEZPUk1fSUQgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcblxuaW1wb3J0IHsgRW1vamlEYXRhIH0gZnJvbSAnQGN0cmwvbmd4LWVtb2ppLW1hcnQvbmd4LWVtb2ppJztcblxuQEluamVjdGFibGUoeyBwcm92aWRlZEluOiAncm9vdCcgfSlcbmV4cG9ydCBjbGFzcyBFbW9qaUZyZXF1ZW50bHlTZXJ2aWNlIHtcbiAgTkFNRVNQQUNFID0gJ2Vtb2ppLW1hcnQnO1xuICBmcmVxdWVudGx5OiB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9IHwgbnVsbCA9IG51bGw7XG4gIGRlZmF1bHRzOiB7IFtrZXk6IHN0cmluZ106IG51bWJlciB9ID0ge307XG4gIGluaXRpYWxpemVkID0gZmFsc2U7XG4gIERFRkFVTFRTID0gW1xuICAgICcrMScsXG4gICAgJ2dyaW5uaW5nJyxcbiAgICAna2lzc2luZ19oZWFydCcsXG4gICAgJ2hlYXJ0X2V5ZXMnLFxuICAgICdsYXVnaGluZycsXG4gICAgJ3N0dWNrX291dF90b25ndWVfd2lua2luZ19leWUnLFxuICAgICdzd2VhdF9zbWlsZScsXG4gICAgJ2pveScsXG4gICAgJ3NjcmVhbScsXG4gICAgJ2Rpc2FwcG9pbnRlZCcsXG4gICAgJ3VuYW11c2VkJyxcbiAgICAnd2VhcnknLFxuICAgICdzb2InLFxuICAgICdzdW5nbGFzc2VzJyxcbiAgICAnaGVhcnQnLFxuICAgICdwb29wJyxcbiAgXTtcbiAgY29uc3RydWN0b3IoQEluamVjdChQTEFURk9STV9JRCkgcHJpdmF0ZSBwbGF0Zm9ybUlkOiBzdHJpbmcpIHt9XG4gIGluaXQoKSB7XG4gICAgdGhpcy5mcmVxdWVudGx5ID0gSlNPTi5wYXJzZShcbiAgICAgIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpICYmXG4gICAgICAgIGxvY2FsU3RvcmFnZS5nZXRJdGVtKGAke3RoaXMuTkFNRVNQQUNFfS5mcmVxdWVudGx5YCkpIHx8XG4gICAgICAgICdudWxsJyxcbiAgICApO1xuICAgIHRoaXMuaW5pdGlhbGl6ZWQgPSB0cnVlO1xuICB9XG4gIGFkZChlbW9qaTogRW1vamlEYXRhKSB7XG4gICAgaWYgKCF0aGlzLmluaXRpYWxpemVkKSB7XG4gICAgICB0aGlzLmluaXQoKTtcbiAgICB9XG4gICAgaWYgKCF0aGlzLmZyZXF1ZW50bHkpIHtcbiAgICAgIHRoaXMuZnJlcXVlbnRseSA9IHRoaXMuZGVmYXVsdHM7XG4gICAgfVxuICAgIGlmICghdGhpcy5mcmVxdWVudGx5W2Vtb2ppLmlkXSkge1xuICAgICAgdGhpcy5mcmVxdWVudGx5W2Vtb2ppLmlkXSA9IDA7XG4gICAgfVxuICAgIHRoaXMuZnJlcXVlbnRseVtlbW9qaS5pZF0gKz0gMTtcblxuICAgIGlmIChpc1BsYXRmb3JtQnJvd3Nlcih0aGlzLnBsYXRmb3JtSWQpKSB7XG4gICAgICBsb2NhbFN0b3JhZ2Uuc2V0SXRlbShgJHt0aGlzLk5BTUVTUEFDRX0ubGFzdGAsIGVtb2ppLmlkKTtcbiAgICAgIGxvY2FsU3RvcmFnZS5zZXRJdGVtKGAke3RoaXMuTkFNRVNQQUNFfS5mcmVxdWVudGx5YCwgSlNPTi5zdHJpbmdpZnkodGhpcy5mcmVxdWVudGx5KSk7XG4gICAgfVxuICB9XG4gIGdldChwZXJMaW5lOiBudW1iZXIsIHRvdGFsTGluZXM6IG51bWJlcikge1xuICAgIGlmICghdGhpcy5pbml0aWFsaXplZCkge1xuICAgICAgdGhpcy5pbml0KCk7XG4gICAgfVxuICAgIGlmICh0aGlzLmZyZXF1ZW50bHkgPT09IG51bGwpIHtcbiAgICAgIHRoaXMuZGVmYXVsdHMgPSB7fTtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IFtdO1xuXG4gICAgICBmb3IgKGxldCBpID0gMDsgaSA8IHBlckxpbmU7IGkrKykge1xuICAgICAgICB0aGlzLmRlZmF1bHRzW3RoaXMuREVGQVVMVFNbaV1dID0gcGVyTGluZSAtIGk7XG4gICAgICAgIHJlc3VsdC5wdXNoKHRoaXMuREVGQVVMVFNbaV0pO1xuICAgICAgfVxuICAgICAgcmV0dXJuIHJlc3VsdDtcbiAgICB9XG5cbiAgICBjb25zdCBxdWFudGl0eSA9IHBlckxpbmUgKiB0b3RhbExpbmVzO1xuICAgIGNvbnN0IGZyZXF1ZW50bHlLZXlzID0gT2JqZWN0LmtleXModGhpcy5mcmVxdWVudGx5KTtcblxuICAgIGNvbnN0IHNvcnRlZCA9IGZyZXF1ZW50bHlLZXlzXG4gICAgICAuc29ydCgoYSwgYikgPT4gdGhpcy5mcmVxdWVudGx5IVthXSAtIHRoaXMuZnJlcXVlbnRseSFbYl0pXG4gICAgICAucmV2ZXJzZSgpO1xuICAgIGNvbnN0IHNsaWNlZCA9IHNvcnRlZC5zbGljZSgwLCBxdWFudGl0eSk7XG5cbiAgICBjb25zdCBsYXN0ID1cbiAgICAgIGlzUGxhdGZvcm1Ccm93c2VyKHRoaXMucGxhdGZvcm1JZCkgJiYgbG9jYWxTdG9yYWdlLmdldEl0ZW0oYCR7dGhpcy5OQU1FU1BBQ0V9Lmxhc3RgKTtcblxuICAgIGlmIChsYXN0ICYmICFzbGljZWQuaW5jbHVkZXMobGFzdCkpIHtcbiAgICAgIHNsaWNlZC5wb3AoKTtcbiAgICAgIHNsaWNlZC5wdXNoKGxhc3QpO1xuICAgIH1cbiAgICByZXR1cm4gc2xpY2VkO1xuICB9XG59XG4iXX0=