@annalib/anna-core 22.3.2 → 22.3.5
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}/annalib-anna-core.mjs +4 -4
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-buyer-approval-icon-template/anna-buyer-approval-icon-template.component.mjs +15 -15
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-deleted-order-icon-template/anna-deleted-order-icon-template.component.mjs +14 -14
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-est-icon-template/anna-est-icon-template.component.mjs +11 -11
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-icon-column/anna-icon-column.component.mjs +36 -36
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-live-icon-template/anna-live-icon-template.component.mjs +15 -15
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-no-data/anna-no-data.component.mjs +22 -22
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-notify-icon-template/anna-notify-icon-template.component.mjs +14 -14
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-pay-for-performance-icon-template/anna-pay-for-performance-icon-template.component.mjs +23 -23
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/components/anna-rejected-icon-template/anna-rejected-icon-template.component.mjs +15 -15
- package/esm2022/lib/anna-core-shared-lib/constants/shared.constant.mjs +44 -0
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/directives/digits-only/digits-only.directive.mjs +284 -284
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/directives/fixed-rows-popup-table/fixed-rows-popup-table.directive.mjs +43 -43
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/directives/show-ellipsis-text/show-ellipsis-text.directive.mjs +38 -38
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/models/anna-generic-data-type.model.mjs +1 -1
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/models/anna-global-dropdown-config.model.mjs +1 -1
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/models/anna-non-editable-gt-models.mjs +11 -11
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/models/anna-sort.model.mjs +6 -6
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/models/anna-tooltip.model.mjs +29 -29
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/pipes/annaConvertArrayToCommaSeperatedValue.pipe.mjs +38 -38
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/pipes/annaConvertZeroOrNullOrUndefined.pipe.mjs +26 -26
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/pipes/annaDateFormatter.pipe.mjs +22 -22
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/pipes/annaFilterSearchedText.pipe.mjs +53 -53
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/pipes/annaReplaceChar.pipe.mjs +25 -25
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/pipes/annaTypeOfData.pipe.mjs +16 -16
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/services/anna-date-time-format.service.mjs +208 -208
- package/esm2022/lib/anna-core-shared-lib/services/anna-filter.service.mjs +1170 -0
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/services/anna-generic-table.service.mjs +151 -151
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/services/anna-global-config.service.mjs +132 -132
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/services/anna-number-format.service.mjs +53 -53
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/services/anna-persisting-filter.service.mjs +66 -66
- package/{esm2020 → esm2022}/lib/anna-core-shared-lib/services/anna-sort.service.mjs +176 -176
- package/esm2022/lib/anna-core.module.mjs +221 -0
- package/{esm2020 → esm2022}/lib/anna-dropdown-lib/components/anna-calendar-filter/anna-calendar-filter.component.mjs +151 -151
- package/esm2022/lib/anna-dropdown-lib/components/anna-week-calendar-filter/anna-week-calendar-filter.component.mjs +364 -0
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-checkbox-filter/anna-column-checkbox-filter.component.mjs +237 -237
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-date-range-filter/anna-column-date-range-filter.component.mjs +180 -180
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-slider-filter/anna-column-slider-filter.component.mjs +306 -306
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-time-filter/anna-column-time-filter.component.mjs +291 -291
- package/esm2022/lib/anna-generic-table-lib/components/anna-non-editable-generic-table/anna-non-editable-generic-table.component.mjs +806 -0
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/components/anna-sort/anna-sort.component.mjs +64 -64
- package/esm2022/lib/anna-generic-table-lib/components/anna-table-virtual-scroll-viewport/anna-table-virtual-scroll-viewport.component.mjs +357 -0
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/directives/anna-fixed-row-size-table-virtual-scroll-strategy/anna-fixed-row-size-table-virtual-scroll-strategy.directive.mjs +189 -189
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/directives/anna-fixed-row-size-table-virtual-scroll-strategy/index.mjs +1 -1
- package/esm2022/lib/anna-generic-table-lib/directives/anna-virtual-table/anna-virtual-table.directive.mjs +178 -0
- package/{esm2020 → esm2022}/lib/anna-generic-table-lib/directives/anna-virtual-table/index.mjs +1 -1
- package/{esm2020 → esm2022}/public-api.mjs +57 -57
- package/{fesm2020 → fesm2022}/annalib-anna-core.mjs +5752 -5721
- package/fesm2022/annalib-anna-core.mjs.map +1 -0
- package/index.d.ts +5 -5
- package/lib/anna-core-shared-lib/components/anna-buyer-approval-icon-template/anna-buyer-approval-icon-template.component.d.ts +8 -8
- package/lib/anna-core-shared-lib/components/anna-deleted-order-icon-template/anna-deleted-order-icon-template.component.d.ts +8 -8
- package/lib/anna-core-shared-lib/components/anna-est-icon-template/anna-est-icon-template.component.d.ts +5 -5
- package/lib/anna-core-shared-lib/components/anna-icon-column/anna-icon-column.component.d.ts +17 -17
- package/lib/anna-core-shared-lib/components/anna-live-icon-template/anna-live-icon-template.component.d.ts +8 -8
- package/lib/anna-core-shared-lib/components/anna-no-data/anna-no-data.component.d.ts +11 -11
- package/lib/anna-core-shared-lib/components/anna-notify-icon-template/anna-notify-icon-template.component.d.ts +8 -8
- package/lib/anna-core-shared-lib/components/anna-pay-for-performance-icon-template/anna-pay-for-performance-icon-template.component.d.ts +12 -12
- package/lib/anna-core-shared-lib/components/anna-rejected-icon-template/anna-rejected-icon-template.component.d.ts +8 -8
- package/lib/anna-core-shared-lib/constants/shared.constant.d.ts +42 -42
- package/lib/anna-core-shared-lib/directives/digits-only/digits-only.directive.d.ts +34 -34
- package/lib/anna-core-shared-lib/directives/fixed-rows-popup-table/fixed-rows-popup-table.directive.d.ts +16 -16
- package/lib/anna-core-shared-lib/directives/show-ellipsis-text/show-ellipsis-text.directive.d.ts +10 -10
- package/lib/anna-core-shared-lib/models/anna-generic-data-type.model.d.ts +16 -16
- package/lib/anna-core-shared-lib/models/anna-global-dropdown-config.model.d.ts +97 -97
- package/lib/anna-core-shared-lib/models/anna-non-editable-gt-models.d.ts +119 -118
- package/lib/anna-core-shared-lib/models/anna-sort.model.d.ts +11 -11
- package/lib/anna-core-shared-lib/models/anna-tooltip.model.d.ts +25 -25
- package/lib/anna-core-shared-lib/pipes/annaConvertArrayToCommaSeperatedValue.pipe.d.ts +9 -9
- package/lib/anna-core-shared-lib/pipes/annaConvertZeroOrNullOrUndefined.pipe.d.ts +9 -9
- package/lib/anna-core-shared-lib/pipes/annaDateFormatter.pipe.d.ts +8 -8
- package/lib/anna-core-shared-lib/pipes/annaFilterSearchedText.pipe.d.ts +9 -9
- package/lib/anna-core-shared-lib/pipes/annaReplaceChar.pipe.d.ts +9 -9
- package/lib/anna-core-shared-lib/pipes/annaTypeOfData.pipe.d.ts +7 -7
- package/lib/anna-core-shared-lib/services/anna-date-time-format.service.d.ts +28 -28
- package/lib/anna-core-shared-lib/services/anna-filter.service.d.ts +154 -154
- package/lib/anna-core-shared-lib/services/anna-generic-table.service.d.ts +27 -27
- package/lib/anna-core-shared-lib/services/anna-global-config.service.d.ts +21 -21
- package/lib/anna-core-shared-lib/services/anna-number-format.service.d.ts +8 -8
- package/lib/anna-core-shared-lib/services/anna-persisting-filter.service.d.ts +9 -9
- package/lib/anna-core-shared-lib/services/anna-sort.service.d.ts +18 -18
- package/lib/anna-core.module.d.ts +45 -45
- package/lib/anna-dropdown-lib/components/anna-calendar-filter/anna-calendar-filter.component.d.ts +45 -45
- package/lib/anna-dropdown-lib/components/anna-week-calendar-filter/anna-week-calendar-filter.component.d.ts +70 -70
- package/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-checkbox-filter/anna-column-checkbox-filter.component.d.ts +60 -60
- package/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-date-range-filter/anna-column-date-range-filter.component.d.ts +53 -53
- package/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-slider-filter/anna-column-slider-filter.component.d.ts +65 -65
- package/lib/anna-generic-table-lib/components/anna-column-filters/anna-column-time-filter/anna-column-time-filter.component.d.ts +83 -83
- package/lib/anna-generic-table-lib/components/anna-non-editable-generic-table/anna-non-editable-generic-table.component.d.ts +175 -174
- package/lib/anna-generic-table-lib/components/anna-sort/anna-sort.component.d.ts +17 -17
- package/lib/anna-generic-table-lib/components/anna-table-virtual-scroll-viewport/anna-table-virtual-scroll-viewport.component.d.ts +141 -141
- package/lib/anna-generic-table-lib/directives/anna-fixed-row-size-table-virtual-scroll-strategy/anna-fixed-row-size-table-virtual-scroll-strategy.directive.d.ts +89 -89
- package/lib/anna-generic-table-lib/directives/anna-fixed-row-size-table-virtual-scroll-strategy/index.d.ts +1 -1
- package/lib/anna-generic-table-lib/directives/anna-virtual-table/anna-virtual-table.directive.d.ts +45 -45
- package/lib/anna-generic-table-lib/directives/anna-virtual-table/index.d.ts +1 -1
- package/package.json +5 -11
- package/public-api.d.ts +42 -42
- package/esm2020/lib/anna-core-shared-lib/constants/shared.constant.mjs +0 -44
- package/esm2020/lib/anna-core-shared-lib/services/anna-filter.service.mjs +0 -1157
- package/esm2020/lib/anna-core.module.mjs +0 -221
- package/esm2020/lib/anna-dropdown-lib/components/anna-week-calendar-filter/anna-week-calendar-filter.component.mjs +0 -364
- package/esm2020/lib/anna-generic-table-lib/components/anna-non-editable-generic-table/anna-non-editable-generic-table.component.mjs +0 -788
- package/esm2020/lib/anna-generic-table-lib/components/anna-table-virtual-scroll-viewport/anna-table-virtual-scroll-viewport.component.mjs +0 -357
- package/esm2020/lib/anna-generic-table-lib/directives/anna-virtual-table/anna-virtual-table.directive.mjs +0 -178
- package/fesm2015/annalib-anna-core.mjs +0 -5857
- package/fesm2015/annalib-anna-core.mjs.map +0 -1
- package/fesm2020/annalib-anna-core.mjs.map +0 -1
package/{esm2020 → esm2022}/lib/anna-generic-table-lib/components/anna-sort/anna-sort.component.mjs
RENAMED
|
@@ -1,64 +1,64 @@
|
|
|
1
|
-
// Angular import statements
|
|
2
|
-
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
|
3
|
-
import { SortTypeEnum } from '../../../anna-core-shared-lib/models/anna-sort.model';
|
|
4
|
-
import { AnnaSortService } from '../../../anna-core-shared-lib/services/anna-sort.service';
|
|
5
|
-
import * as i0 from "@angular/core";
|
|
6
|
-
import * as i1 from "../../../anna-core-shared-lib/services/anna-sort.service";
|
|
7
|
-
import * as i2 from "@angular/common";
|
|
8
|
-
//Add onChange push change detection
|
|
9
|
-
export class AnnaSortComponent {
|
|
10
|
-
constructor(annaSortService) {
|
|
11
|
-
this.annaSortService = annaSortService;
|
|
12
|
-
this.sortOptionClicked = new EventEmitter();
|
|
13
|
-
this.sortOptions = [
|
|
14
|
-
{
|
|
15
|
-
sortType: SortTypeEnum.ASC,
|
|
16
|
-
isOptionActive: false,
|
|
17
|
-
text: 'A to Z',
|
|
18
|
-
},
|
|
19
|
-
{
|
|
20
|
-
sortType: SortTypeEnum.DESC,
|
|
21
|
-
isOptionActive: false,
|
|
22
|
-
text: 'Z to A',
|
|
23
|
-
},
|
|
24
|
-
{
|
|
25
|
-
sortType: SortTypeEnum.DEFAULT,
|
|
26
|
-
isOptionActive: false,
|
|
27
|
-
text: 'Default',
|
|
28
|
-
},
|
|
29
|
-
];
|
|
30
|
-
}
|
|
31
|
-
ngOnChanges(changes) {
|
|
32
|
-
if (changes["sortObjectKey"] && changes["sortObjectKey"].currentValue) {
|
|
33
|
-
let sortType = this.annaSortService.columnSortState.get(this.sortObjectKey);
|
|
34
|
-
this.setSortType(sortType);
|
|
35
|
-
}
|
|
36
|
-
}
|
|
37
|
-
sortOptionChanged(index, sortType) {
|
|
38
|
-
this.sortOptions.forEach((item) => (item.isOptionActive = false));
|
|
39
|
-
this.sortOptions[index].isOptionActive = true;
|
|
40
|
-
this.sortOptionClicked.emit(sortType);
|
|
41
|
-
}
|
|
42
|
-
ngOnInit() {
|
|
43
|
-
this.annaSortService.updateSortTypeSubject.subscribe((item) => {
|
|
44
|
-
this.setSortType(item);
|
|
45
|
-
});
|
|
46
|
-
}
|
|
47
|
-
setSortType(option) {
|
|
48
|
-
option = option ? option : SortTypeEnum.DEFAULT;
|
|
49
|
-
this.sortOptions.forEach(item => item.isOptionActive = false);
|
|
50
|
-
let index = this.sortOptions.findIndex(item => item.sortType == option);
|
|
51
|
-
this.sortOptions[index].isOptionActive = true;
|
|
52
|
-
}
|
|
53
|
-
}
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "
|
|
57
|
-
type: Component,
|
|
58
|
-
args: [{ selector: 'anna-core-sort-lib', changeDetection: ChangeDetectionStrategy.OnPush, template: "<p class=\"sort-container\">\r\n <button\r\n class=\"sort-btn\"\r\n *ngFor=\"let option of sortOptions; let i = index\"\r\n (click)=\"sortOptionChanged(i, option.sortType)\"\r\n [ngClass]=\"{ active: option.isOptionActive }\"\r\n >\r\n {{option.text}}\r\n </button>\r\n</p>", styles: [".sort-btn{background
|
|
59
|
-
}], ctorParameters: function () { return [{ type: i1.AnnaSortService }]; }, propDecorators: { sortObjectKey: [{
|
|
60
|
-
type: Input
|
|
61
|
-
}], sortOptionClicked: [{
|
|
62
|
-
type: Output
|
|
63
|
-
}] } });
|
|
64
|
-
//# sourceMappingURL=data:application/json;base64,
|
|
1
|
+
// Angular import statements
|
|
2
|
+
import { ChangeDetectionStrategy, Component, EventEmitter, Input, Output } from '@angular/core';
|
|
3
|
+
import { SortTypeEnum } from '../../../anna-core-shared-lib/models/anna-sort.model';
|
|
4
|
+
import { AnnaSortService } from '../../../anna-core-shared-lib/services/anna-sort.service';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
import * as i1 from "../../../anna-core-shared-lib/services/anna-sort.service";
|
|
7
|
+
import * as i2 from "@angular/common";
|
|
8
|
+
//Add onChange push change detection
|
|
9
|
+
export class AnnaSortComponent {
|
|
10
|
+
constructor(annaSortService) {
|
|
11
|
+
this.annaSortService = annaSortService;
|
|
12
|
+
this.sortOptionClicked = new EventEmitter();
|
|
13
|
+
this.sortOptions = [
|
|
14
|
+
{
|
|
15
|
+
sortType: SortTypeEnum.ASC,
|
|
16
|
+
isOptionActive: false,
|
|
17
|
+
text: 'A to Z',
|
|
18
|
+
},
|
|
19
|
+
{
|
|
20
|
+
sortType: SortTypeEnum.DESC,
|
|
21
|
+
isOptionActive: false,
|
|
22
|
+
text: 'Z to A',
|
|
23
|
+
},
|
|
24
|
+
{
|
|
25
|
+
sortType: SortTypeEnum.DEFAULT,
|
|
26
|
+
isOptionActive: false,
|
|
27
|
+
text: 'Default',
|
|
28
|
+
},
|
|
29
|
+
];
|
|
30
|
+
}
|
|
31
|
+
ngOnChanges(changes) {
|
|
32
|
+
if (changes["sortObjectKey"] && changes["sortObjectKey"].currentValue) {
|
|
33
|
+
let sortType = this.annaSortService.columnSortState.get(this.sortObjectKey);
|
|
34
|
+
this.setSortType(sortType);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
sortOptionChanged(index, sortType) {
|
|
38
|
+
this.sortOptions.forEach((item) => (item.isOptionActive = false));
|
|
39
|
+
this.sortOptions[index].isOptionActive = true;
|
|
40
|
+
this.sortOptionClicked.emit(sortType);
|
|
41
|
+
}
|
|
42
|
+
ngOnInit() {
|
|
43
|
+
this.annaSortService.updateSortTypeSubject.subscribe((item) => {
|
|
44
|
+
this.setSortType(item);
|
|
45
|
+
});
|
|
46
|
+
}
|
|
47
|
+
setSortType(option) {
|
|
48
|
+
option = option ? option : SortTypeEnum.DEFAULT;
|
|
49
|
+
this.sortOptions.forEach(item => item.isOptionActive = false);
|
|
50
|
+
let index = this.sortOptions.findIndex(item => item.sortType == option);
|
|
51
|
+
this.sortOptions[index].isOptionActive = true;
|
|
52
|
+
}
|
|
53
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AnnaSortComponent, deps: [{ token: i1.AnnaSortService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
54
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AnnaSortComponent, selector: "anna-core-sort-lib", inputs: { sortObjectKey: "sortObjectKey" }, outputs: { sortOptionClicked: "sortOptionClicked" }, usesOnChanges: true, ngImport: i0, template: "<p class=\"sort-container\">\r\n <button\r\n class=\"sort-btn\"\r\n *ngFor=\"let option of sortOptions; let i = index\"\r\n (click)=\"sortOptionChanged(i, option.sortType)\"\r\n [ngClass]=\"{ active: option.isOptionActive }\"\r\n >\r\n {{option.text}}\r\n </button>\r\n</p>", styles: [".sort-btn{background:#fff;border:none;border-right:1px solid #1b88ff;text-decoration:underline;font-family:Roboto;font-size:14px;font-weight:400;font-stretch:normal;font-style:normal;line-height:1.07;letter-spacing:normal;color:#1b88ff;cursor:pointer;flex:1;text-align:center}.sort-btn:last-of-type{border-right:none}.sort-btn.active{color:#202b47;text-decoration:none}p.sort-container{margin-top:8px;padding-bottom:8px;border-bottom:1px solid #e6e6e6;margin-bottom:0;display:flex}\n"], dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }], changeDetection: i0.ChangeDetectionStrategy.OnPush }); }
|
|
55
|
+
}
|
|
56
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AnnaSortComponent, decorators: [{
|
|
57
|
+
type: Component,
|
|
58
|
+
args: [{ selector: 'anna-core-sort-lib', changeDetection: ChangeDetectionStrategy.OnPush, template: "<p class=\"sort-container\">\r\n <button\r\n class=\"sort-btn\"\r\n *ngFor=\"let option of sortOptions; let i = index\"\r\n (click)=\"sortOptionChanged(i, option.sortType)\"\r\n [ngClass]=\"{ active: option.isOptionActive }\"\r\n >\r\n {{option.text}}\r\n </button>\r\n</p>", styles: [".sort-btn{background:#fff;border:none;border-right:1px solid #1b88ff;text-decoration:underline;font-family:Roboto;font-size:14px;font-weight:400;font-stretch:normal;font-style:normal;line-height:1.07;letter-spacing:normal;color:#1b88ff;cursor:pointer;flex:1;text-align:center}.sort-btn:last-of-type{border-right:none}.sort-btn.active{color:#202b47;text-decoration:none}p.sort-container{margin-top:8px;padding-bottom:8px;border-bottom:1px solid #e6e6e6;margin-bottom:0;display:flex}\n"] }]
|
|
59
|
+
}], ctorParameters: function () { return [{ type: i1.AnnaSortService }]; }, propDecorators: { sortObjectKey: [{
|
|
60
|
+
type: Input
|
|
61
|
+
}], sortOptionClicked: [{
|
|
62
|
+
type: Output
|
|
63
|
+
}] } });
|
|
64
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5uYS1zb3J0LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FubmEtY29yZS9zcmMvbGliL2FubmEtZ2VuZXJpYy10YWJsZS1saWIvY29tcG9uZW50cy9hbm5hLXNvcnQvYW5uYS1zb3J0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FubmEtY29yZS9zcmMvbGliL2FubmEtZ2VuZXJpYy10YWJsZS1saWIvY29tcG9uZW50cy9hbm5hLXNvcnQvYW5uYS1zb3J0LmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLDRCQUE0QjtBQUM1QixPQUFPLEVBQUUsdUJBQXVCLEVBQUUsU0FBUyxFQUFFLFlBQVksRUFBRSxLQUFLLEVBQWEsTUFBTSxFQUFpQixNQUFNLGVBQWUsQ0FBQztBQUMxSCxPQUFPLEVBQXdCLFlBQVksRUFBRSxNQUFNLHNEQUFzRCxDQUFDO0FBQzFHLE9BQU8sRUFBRSxlQUFlLEVBQUUsTUFBTSwwREFBMEQsQ0FBQzs7OztBQUUzRixvQ0FBb0M7QUFPcEMsTUFBTSxPQUFPLGlCQUFpQjtJQXVCNUIsWUFBb0IsZUFBZ0M7UUFBaEMsb0JBQWUsR0FBZixlQUFlLENBQWlCO1FBcEIxQyxzQkFBaUIsR0FBRyxJQUFJLFlBQVksRUFBWSxDQUFDO1FBRTNELGdCQUFXLEdBQWlCO1lBQzFCO2dCQUNFLFFBQVEsRUFBRSxZQUFZLENBQUMsR0FBRztnQkFDMUIsY0FBYyxFQUFFLEtBQUs7Z0JBQ3JCLElBQUksRUFBRSxRQUFRO2FBQ2Y7WUFDRDtnQkFDRSxRQUFRLEVBQUUsWUFBWSxDQUFDLElBQUk7Z0JBQzNCLGNBQWMsRUFBRSxLQUFLO2dCQUNyQixJQUFJLEVBQUUsUUFBUTthQUNmO1lBQ0Q7Z0JBQ0UsUUFBUSxFQUFFLFlBQVksQ0FBQyxPQUFPO2dCQUM5QixjQUFjLEVBQUUsS0FBSztnQkFDckIsSUFBSSxFQUFFLFNBQVM7YUFDaEI7U0FDRixDQUFDO0lBRXFELENBQUM7SUFFeEQsV0FBVyxDQUFDLE9BQXNCO1FBQ2hDLElBQUcsT0FBTyxDQUFDLGVBQWUsQ0FBQyxJQUFJLE9BQU8sQ0FBQyxlQUFlLENBQUMsQ0FBQyxZQUFZLEVBQUM7WUFDbkUsSUFBSSxRQUFRLEdBQUcsSUFBSSxDQUFDLGVBQWUsQ0FBQyxlQUFlLENBQUMsR0FBRyxDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsQ0FBQztZQUM1RSxJQUFJLENBQUMsV0FBVyxDQUFDLFFBQVEsQ0FBQyxDQUFDO1NBQzVCO0lBRUgsQ0FBQztJQUVELGlCQUFpQixDQUFDLEtBQWEsRUFBRSxRQUFrQjtRQUNqRCxJQUFJLENBQUMsV0FBVyxDQUFDLE9BQU8sQ0FBQyxDQUFDLElBQUksRUFBRSxFQUFFLENBQUMsQ0FBQyxJQUFJLENBQUMsY0FBYyxHQUFHLEtBQUssQ0FBQyxDQUFDLENBQUM7UUFDbEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO1FBQzlDLElBQUksQ0FBQyxpQkFBaUIsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLENBQUM7SUFDeEMsQ0FBQztJQUVELFFBQVE7UUFDTixJQUFJLENBQUMsZUFBZSxDQUFDLHFCQUFxQixDQUFDLFNBQVMsQ0FBQyxDQUFDLElBQVksRUFBRSxFQUFFO1lBQ3BFLElBQUksQ0FBQyxXQUFXLENBQUMsSUFBSSxDQUFDLENBQUM7UUFDekIsQ0FBQyxDQUFDLENBQUM7SUFDTCxDQUFDO0lBRUQsV0FBVyxDQUFDLE1BQWM7UUFDeEIsTUFBTSxHQUFHLE1BQU0sQ0FBQyxDQUFDLENBQUMsTUFBTSxDQUFDLENBQUMsQ0FBQSxZQUFZLENBQUMsT0FBTyxDQUFDO1FBQy9DLElBQUksQ0FBQyxXQUFXLENBQUMsT0FBTyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsR0FBRyxLQUFLLENBQUMsQ0FBQztRQUM5RCxJQUFJLEtBQUssR0FBRyxJQUFJLENBQUMsV0FBVyxDQUFDLFNBQVMsQ0FBQyxJQUFJLENBQUMsRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksTUFBTSxDQUFDLENBQUM7UUFDeEUsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUMsQ0FBQyxjQUFjLEdBQUcsSUFBSSxDQUFDO0lBQ2hELENBQUM7K0dBbERVLGlCQUFpQjttR0FBakIsaUJBQWlCLGdMQ1o5QiwrVEFTSTs7NEZER1MsaUJBQWlCO2tCQU43QixTQUFTOytCQUNFLG9CQUFvQixtQkFHYix1QkFBdUIsQ0FBQyxNQUFNO3NHQUl0QyxhQUFhO3NCQUFyQixLQUFLO2dCQUNJLGlCQUFpQjtzQkFBMUIsTUFBTSIsInNvdXJjZXNDb250ZW50IjpbIi8vIEFuZ3VsYXIgaW1wb3J0IHN0YXRlbWVudHNcclxuaW1wb3J0IHsgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksIENvbXBvbmVudCwgRXZlbnRFbWl0dGVyLCBJbnB1dCwgT25DaGFuZ2VzLCBPdXRwdXQsIFNpbXBsZUNoYW5nZXMgfSBmcm9tICdAYW5ndWxhci9jb3JlJztcclxuaW1wb3J0IHsgU29ydE9wdGlvbiwgU29ydFR5cGUsIFNvcnRUeXBlRW51bSB9IGZyb20gJy4uLy4uLy4uL2FubmEtY29yZS1zaGFyZWQtbGliL21vZGVscy9hbm5hLXNvcnQubW9kZWwnO1xyXG5pbXBvcnQgeyBBbm5hU29ydFNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9hbm5hLWNvcmUtc2hhcmVkLWxpYi9zZXJ2aWNlcy9hbm5hLXNvcnQuc2VydmljZSc7XHJcblxyXG4vL0FkZCBvbkNoYW5nZSBwdXNoIGNoYW5nZSBkZXRlY3Rpb25cclxuQENvbXBvbmVudCh7XHJcbiAgc2VsZWN0b3I6ICdhbm5hLWNvcmUtc29ydC1saWInLFxyXG4gIHRlbXBsYXRlVXJsOiAnLi9hbm5hLXNvcnQuY29tcG9uZW50Lmh0bWwnLFxyXG4gIHN0eWxlVXJsczogWycuL2FubmEtc29ydC5jb21wb25lbnQuc2NzcyddLFxyXG4gIGNoYW5nZURldGVjdGlvbjogQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3kuT25QdXNoXHJcbn0pXHJcbmV4cG9ydCBjbGFzcyBBbm5hU29ydENvbXBvbmVudCBpbXBsZW1lbnRzIE9uQ2hhbmdlc3tcclxuICBcclxuICBASW5wdXQoKSBzb3J0T2JqZWN0S2V5OiBzdHJpbmc7XHJcbiAgQE91dHB1dCgpIHNvcnRPcHRpb25DbGlja2VkID0gbmV3IEV2ZW50RW1pdHRlcjxTb3J0VHlwZT4oKTtcclxuXHJcbiAgc29ydE9wdGlvbnM6IFNvcnRPcHRpb25bXSA9IFtcclxuICAgIHtcclxuICAgICAgc29ydFR5cGU6IFNvcnRUeXBlRW51bS5BU0MsXHJcbiAgICAgIGlzT3B0aW9uQWN0aXZlOiBmYWxzZSxcclxuICAgICAgdGV4dDogJ0EgdG8gWicsXHJcbiAgICB9LFxyXG4gICAge1xyXG4gICAgICBzb3J0VHlwZTogU29ydFR5cGVFbnVtLkRFU0MsXHJcbiAgICAgIGlzT3B0aW9uQWN0aXZlOiBmYWxzZSxcclxuICAgICAgdGV4dDogJ1ogdG8gQScsXHJcbiAgICB9LFxyXG4gICAge1xyXG4gICAgICBzb3J0VHlwZTogU29ydFR5cGVFbnVtLkRFRkFVTFQsXHJcbiAgICAgIGlzT3B0aW9uQWN0aXZlOiBmYWxzZSxcclxuICAgICAgdGV4dDogJ0RlZmF1bHQnLFxyXG4gICAgfSxcclxuICBdO1xyXG5cclxuICBjb25zdHJ1Y3Rvcihwcml2YXRlIGFubmFTb3J0U2VydmljZTogQW5uYVNvcnRTZXJ2aWNlKSB7fVxyXG4gIFxyXG4gIG5nT25DaGFuZ2VzKGNoYW5nZXM6IFNpbXBsZUNoYW5nZXMpOiB2b2lkIHtcclxuICAgIGlmKGNoYW5nZXNbXCJzb3J0T2JqZWN0S2V5XCJdICYmIGNoYW5nZXNbXCJzb3J0T2JqZWN0S2V5XCJdLmN1cnJlbnRWYWx1ZSl7XHJcbiAgICAgIGxldCBzb3J0VHlwZSA9IHRoaXMuYW5uYVNvcnRTZXJ2aWNlLmNvbHVtblNvcnRTdGF0ZS5nZXQodGhpcy5zb3J0T2JqZWN0S2V5KTtcclxuICAgICAgdGhpcy5zZXRTb3J0VHlwZShzb3J0VHlwZSk7XHJcbiAgICB9XHJcblxyXG4gIH1cclxuXHJcbiAgc29ydE9wdGlvbkNoYW5nZWQoaW5kZXg6IG51bWJlciwgc29ydFR5cGU6IFNvcnRUeXBlKSB7XHJcbiAgICB0aGlzLnNvcnRPcHRpb25zLmZvckVhY2goKGl0ZW0pID0+IChpdGVtLmlzT3B0aW9uQWN0aXZlID0gZmFsc2UpKTtcclxuICAgIHRoaXMuc29ydE9wdGlvbnNbaW5kZXhdLmlzT3B0aW9uQWN0aXZlID0gdHJ1ZTtcclxuICAgIHRoaXMuc29ydE9wdGlvbkNsaWNrZWQuZW1pdChzb3J0VHlwZSk7XHJcbiAgfVxyXG5cclxuICBuZ09uSW5pdCgpOiB2b2lkIHtcclxuICAgIHRoaXMuYW5uYVNvcnRTZXJ2aWNlLnVwZGF0ZVNvcnRUeXBlU3ViamVjdC5zdWJzY3JpYmUoKGl0ZW06IHN0cmluZykgPT4ge1xyXG4gICAgICB0aGlzLnNldFNvcnRUeXBlKGl0ZW0pO1xyXG4gICAgfSk7XHJcbiAgfVxyXG5cclxuICBzZXRTb3J0VHlwZShvcHRpb246IHN0cmluZyl7XHJcbiAgICBvcHRpb24gPSBvcHRpb24gPyBvcHRpb24gOlNvcnRUeXBlRW51bS5ERUZBVUxUO1xyXG4gICAgdGhpcy5zb3J0T3B0aW9ucy5mb3JFYWNoKGl0ZW0gPT4gaXRlbS5pc09wdGlvbkFjdGl2ZSA9IGZhbHNlKTtcclxuICAgIGxldCBpbmRleCA9IHRoaXMuc29ydE9wdGlvbnMuZmluZEluZGV4KGl0ZW0gPT4gaXRlbS5zb3J0VHlwZSA9PSBvcHRpb24pO1xyXG4gICAgdGhpcy5zb3J0T3B0aW9uc1tpbmRleF0uaXNPcHRpb25BY3RpdmUgPSB0cnVlO1xyXG4gIH1cclxufVxyXG4iLCI8cCBjbGFzcz1cInNvcnQtY29udGFpbmVyXCI+XHJcbiAgICA8YnV0dG9uXHJcbiAgICAgICAgY2xhc3M9XCJzb3J0LWJ0blwiXHJcbiAgICAgICAgKm5nRm9yPVwibGV0IG9wdGlvbiBvZiBzb3J0T3B0aW9uczsgbGV0IGkgPSBpbmRleFwiXHJcbiAgICAgICAgKGNsaWNrKT1cInNvcnRPcHRpb25DaGFuZ2VkKGksIG9wdGlvbi5zb3J0VHlwZSlcIlxyXG4gICAgICAgIFtuZ0NsYXNzXT1cInsgYWN0aXZlOiBvcHRpb24uaXNPcHRpb25BY3RpdmUgfVwiXHJcbiAgICA+XHJcbiAgICAgICAge3tvcHRpb24udGV4dH19XHJcbiAgICA8L2J1dHRvbj5cclxuPC9wPiJdfQ==
|
|
@@ -0,0 +1,357 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* @license
|
|
3
|
+
* Copyright Google LLC All Rights Reserved.
|
|
4
|
+
*
|
|
5
|
+
* Use of this source code is governed by an MIT-style license that can be
|
|
6
|
+
* found in the LICENSE file at https://angular.io/license
|
|
7
|
+
*/
|
|
8
|
+
import { Directionality } from "@angular/cdk/bidi";
|
|
9
|
+
import { ChangeDetectionStrategy, ChangeDetectorRef, Component, ElementRef, Inject, Input, NgZone, Optional, Output, ViewChild, ViewEncapsulation } from "@angular/core";
|
|
10
|
+
import { animationFrameScheduler, asapScheduler, Observable, Subject, Subscription } from "rxjs";
|
|
11
|
+
import { auditTime, startWith, takeUntil } from "rxjs/operators";
|
|
12
|
+
import { CdkVirtualScrollViewport, CdkScrollable, VIRTUAL_SCROLL_STRATEGY, ScrollDispatcher, ViewportRuler } from "@angular/cdk/scrolling";
|
|
13
|
+
import { AnnaGtHelperService } from '../../../anna-core-shared-lib/services/anna-generic-table.service';
|
|
14
|
+
import * as i0 from "@angular/core";
|
|
15
|
+
import * as i1 from "@angular/cdk/bidi";
|
|
16
|
+
import * as i2 from "@angular/cdk/scrolling";
|
|
17
|
+
import * as i3 from "../../../anna-core-shared-lib/services/anna-generic-table.service";
|
|
18
|
+
/** Checks if the given ranges are equal. */
|
|
19
|
+
function rangesEqual(r1, r2) {
|
|
20
|
+
return r1.start == r2.start && r1.end == r2.end;
|
|
21
|
+
}
|
|
22
|
+
/**
|
|
23
|
+
* Scheduler to be used for scroll events. Needs to fall back to
|
|
24
|
+
* something that doesn't rely on requestAnimationFrame on environments
|
|
25
|
+
* that don't support it (e.g. server-side rendering).
|
|
26
|
+
*/
|
|
27
|
+
const SCROLL_SCHEDULER = typeof requestAnimationFrame !== "undefined"
|
|
28
|
+
? animationFrameScheduler
|
|
29
|
+
: asapScheduler;
|
|
30
|
+
/**
|
|
31
|
+
* A viewport that virtualizes its scrolling with the help of `CdkVirtualForOf`.
|
|
32
|
+
* Uses `top: #px` instead of `transform: translateY(#px)` like the cdk virtual scroll viewport does
|
|
33
|
+
* which avoids flickering of elements in the transformed container with `position: sticky`.
|
|
34
|
+
*/
|
|
35
|
+
export class AnnaTableVirtualScrollViewportComponent extends CdkScrollable {
|
|
36
|
+
/** The direction the viewport scrolls. */
|
|
37
|
+
get orientation() {
|
|
38
|
+
return this._orientation;
|
|
39
|
+
}
|
|
40
|
+
set orientation(orientation) {
|
|
41
|
+
if (this._orientation !== orientation) {
|
|
42
|
+
this._orientation = orientation;
|
|
43
|
+
this._calculateSpacerSize();
|
|
44
|
+
}
|
|
45
|
+
}
|
|
46
|
+
constructor(elementRef, _changeDetectorRef, ngZone, _scrollStrategy, dir, scrollDispatcher, viewportRuler, annaGtService) {
|
|
47
|
+
super(elementRef, scrollDispatcher, ngZone, dir);
|
|
48
|
+
this.elementRef = elementRef;
|
|
49
|
+
this._changeDetectorRef = _changeDetectorRef;
|
|
50
|
+
this._scrollStrategy = _scrollStrategy;
|
|
51
|
+
this.annaGtService = annaGtService;
|
|
52
|
+
/** Emits when the viewport is detached from a CdkVirtualForOf. */
|
|
53
|
+
this._detachedSubject = new Subject();
|
|
54
|
+
/** Emits when the rendered range changes. */
|
|
55
|
+
this._renderedRangeSubject = new Subject();
|
|
56
|
+
this._orientation = "vertical";
|
|
57
|
+
// Note: we don't use the typical EventEmitter here because we need to subscribe to the scroll
|
|
58
|
+
// strategy lazily (i.e. only if the user is actually listening to the events). We do this because
|
|
59
|
+
// depending on how the strategy calculates the scrolled index, it may come at a cost to
|
|
60
|
+
// performance.
|
|
61
|
+
/** Emits when the index of the first element visible in the viewport changes. */
|
|
62
|
+
this.scrolledIndexChange = new Observable((observer) => this._scrollStrategy.scrolledIndexChange.subscribe(index => Promise.resolve().then(() => this.ngZone.run(() => observer.next(index)))));
|
|
63
|
+
/** A stream that emits whenever the rendered range changes. */
|
|
64
|
+
this.renderedRangeStream = this._renderedRangeSubject;
|
|
65
|
+
/**
|
|
66
|
+
* The total size of all content (in pixels), including content that is not currently rendered.
|
|
67
|
+
*/
|
|
68
|
+
this._totalContentSize = 0;
|
|
69
|
+
/** A string representing the `style.width` property value to be used for the spacer element. */
|
|
70
|
+
this._totalContentWidth = "";
|
|
71
|
+
/** A string representing the `style.height` property value to be used for the spacer element. */
|
|
72
|
+
this._totalContentHeight = "";
|
|
73
|
+
/** The currently rendered range of indices. */
|
|
74
|
+
this._renderedRange = { start: 0, end: 0 };
|
|
75
|
+
/** The length of the data bound to this viewport (in number of items). */
|
|
76
|
+
this._dataLength = 0;
|
|
77
|
+
/** The size of the viewport (in pixels). */
|
|
78
|
+
this._viewportSize = 0;
|
|
79
|
+
/** The last rendered content offset that was set. */
|
|
80
|
+
this._renderedContentOffset = 0;
|
|
81
|
+
/**
|
|
82
|
+
* Whether the last rendered content offset was to the end of the content (and therefore needs to
|
|
83
|
+
* be rewritten as an offset to the start of the content).
|
|
84
|
+
*/
|
|
85
|
+
this._renderedContentOffsetNeedsRewrite = false;
|
|
86
|
+
/** Whether there is a pending change detection cycle. */
|
|
87
|
+
this._isChangeDetectionPending = false;
|
|
88
|
+
/** A list of functions to run after the next change detection cycle. */
|
|
89
|
+
this._runAfterChangeDetection = [];
|
|
90
|
+
/** Subscription to changes in the viewport size. */
|
|
91
|
+
this._viewportChanges = Subscription.EMPTY;
|
|
92
|
+
if (!_scrollStrategy) {
|
|
93
|
+
throw Error('Error: cdk-virtual-scroll-viewport requires the "itemSize" property to be set.');
|
|
94
|
+
}
|
|
95
|
+
this._viewportChanges = viewportRuler.change().subscribe(() => {
|
|
96
|
+
this.checkViewportSize();
|
|
97
|
+
});
|
|
98
|
+
}
|
|
99
|
+
ngOnInit() {
|
|
100
|
+
super.ngOnInit();
|
|
101
|
+
// It's still too early to measure the viewport at this point. Deferring with a promise allows
|
|
102
|
+
// the Viewport to be rendered with the correct size before we measure. We run this outside the
|
|
103
|
+
// zone to avoid causing more change detection cycles. We handle the change detection loop
|
|
104
|
+
// ourselves instead.
|
|
105
|
+
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {
|
|
106
|
+
this._measureViewportSize();
|
|
107
|
+
this._scrollStrategy.attach(this);
|
|
108
|
+
this.elementScrolled()
|
|
109
|
+
.pipe(
|
|
110
|
+
// Start off with a fake scroll event so we properly detect our initial position.
|
|
111
|
+
startWith(null),
|
|
112
|
+
// Collect multiple events into one until the next animation frame. This way if
|
|
113
|
+
// there are multiple scroll events in the same frame we only need to recheck
|
|
114
|
+
// our layout once.
|
|
115
|
+
auditTime(0, SCROLL_SCHEDULER))
|
|
116
|
+
.subscribe(() => { this._scrollStrategy.onContentScrolled(); this.annaGtService.virtualScrollSubject.next(true); });
|
|
117
|
+
this._markChangeDetectionNeeded();
|
|
118
|
+
}));
|
|
119
|
+
}
|
|
120
|
+
ngOnDestroy() {
|
|
121
|
+
this.detach();
|
|
122
|
+
this._scrollStrategy.detach();
|
|
123
|
+
// Complete all subjects
|
|
124
|
+
this._renderedRangeSubject.complete();
|
|
125
|
+
this._detachedSubject.complete();
|
|
126
|
+
this._viewportChanges.unsubscribe();
|
|
127
|
+
super.ngOnDestroy();
|
|
128
|
+
}
|
|
129
|
+
/** Attaches a `CdkVirtualScrollRepeater` to this viewport. */
|
|
130
|
+
attach(forOf) {
|
|
131
|
+
if (this._forOf) {
|
|
132
|
+
throw Error("CdkVirtualScrollViewport is already attached.");
|
|
133
|
+
}
|
|
134
|
+
// Subscribe to the data stream of the CdkVirtualForOf to keep track of when the data length
|
|
135
|
+
// changes. Run outside the zone to avoid triggering change detection, since we're managing the
|
|
136
|
+
// change detection loop ourselves.
|
|
137
|
+
this.ngZone.runOutsideAngular(() => {
|
|
138
|
+
this._forOf = forOf;
|
|
139
|
+
this._forOf.dataStream
|
|
140
|
+
.pipe(takeUntil(this._detachedSubject))
|
|
141
|
+
.subscribe(data => {
|
|
142
|
+
const newLength = data.length;
|
|
143
|
+
if (newLength !== this._dataLength) {
|
|
144
|
+
this._dataLength = newLength;
|
|
145
|
+
this._scrollStrategy.onDataLengthChanged();
|
|
146
|
+
}
|
|
147
|
+
this._doChangeDetection();
|
|
148
|
+
});
|
|
149
|
+
});
|
|
150
|
+
}
|
|
151
|
+
/** Detaches the current `CdkVirtualForOf`. */
|
|
152
|
+
detach() {
|
|
153
|
+
this._forOf = null;
|
|
154
|
+
this._detachedSubject.next();
|
|
155
|
+
}
|
|
156
|
+
/** Gets the length of the data bound to this viewport (in number of items). */
|
|
157
|
+
getDataLength() {
|
|
158
|
+
return this._dataLength;
|
|
159
|
+
}
|
|
160
|
+
/** Gets the size of the viewport (in pixels). */
|
|
161
|
+
getViewportSize() {
|
|
162
|
+
return this._viewportSize;
|
|
163
|
+
}
|
|
164
|
+
// TODO(mmalerba): This is technically out of sync with what's really rendered until a render
|
|
165
|
+
// cycle happens. I'm being careful to only call it after the render cycle is complete and before
|
|
166
|
+
// setting it to something else, but its error prone and should probably be split into
|
|
167
|
+
// `pendingRange` and `renderedRange`, the latter reflecting whats actually in the DOM.
|
|
168
|
+
/** Get the current rendered range of items. */
|
|
169
|
+
getRenderedRange() {
|
|
170
|
+
return this._renderedRange;
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Sets the total size of all content (in pixels), including content that is not currently
|
|
174
|
+
* rendered.
|
|
175
|
+
*/
|
|
176
|
+
setTotalContentSize(size) {
|
|
177
|
+
if (this._totalContentSize !== size) {
|
|
178
|
+
this._totalContentSize = size;
|
|
179
|
+
this._calculateSpacerSize();
|
|
180
|
+
this._markChangeDetectionNeeded();
|
|
181
|
+
}
|
|
182
|
+
}
|
|
183
|
+
/** Sets the currently rendered range of indices. */
|
|
184
|
+
setRenderedRange(range) {
|
|
185
|
+
if (!rangesEqual(this._renderedRange, range)) {
|
|
186
|
+
this._renderedRangeSubject.next((this._renderedRange = range));
|
|
187
|
+
this._markChangeDetectionNeeded(() => this._scrollStrategy.onContentRendered());
|
|
188
|
+
}
|
|
189
|
+
}
|
|
190
|
+
/**
|
|
191
|
+
* Gets the offset from the start of the viewport to the start of the rendered data (in pixels).
|
|
192
|
+
*/
|
|
193
|
+
getOffsetToRenderedContentStart() {
|
|
194
|
+
return this._renderedContentOffsetNeedsRewrite
|
|
195
|
+
? null
|
|
196
|
+
: this._renderedContentOffset;
|
|
197
|
+
}
|
|
198
|
+
/**
|
|
199
|
+
* Sets the offset from the start of the viewport to either the start or end of the rendered data
|
|
200
|
+
* (in pixels).
|
|
201
|
+
*/
|
|
202
|
+
setRenderedContentOffset(offset) {
|
|
203
|
+
let top = `${Number(offset)}px`;
|
|
204
|
+
this._renderedContentOffset = offset;
|
|
205
|
+
if (this._renderedContentTransform != top) {
|
|
206
|
+
// We know this value is safe because we parse `offset` with `Number()` before passing it
|
|
207
|
+
// into the string.
|
|
208
|
+
this._renderedContentTransform = top;
|
|
209
|
+
this._markChangeDetectionNeeded(() => {
|
|
210
|
+
if (this._renderedContentOffsetNeedsRewrite) {
|
|
211
|
+
this._renderedContentOffset -= this.measureRenderedContentSize();
|
|
212
|
+
this._renderedContentOffsetNeedsRewrite = false;
|
|
213
|
+
this.setRenderedContentOffset(this._renderedContentOffset);
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
this._scrollStrategy.onRenderedOffsetChanged();
|
|
217
|
+
}
|
|
218
|
+
});
|
|
219
|
+
}
|
|
220
|
+
}
|
|
221
|
+
/**
|
|
222
|
+
* Scrolls to the given offset from the start of the viewport. Please note that this is not always
|
|
223
|
+
* the same as setting `scrollTop` or `scrollLeft`. In a horizontal viewport with right-to-left
|
|
224
|
+
* direction, this would be the equivalent of setting a fictional `scrollRight` property.
|
|
225
|
+
* @param offset The offset to scroll to.
|
|
226
|
+
* @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.
|
|
227
|
+
*/
|
|
228
|
+
scrollToOffset(offset, behavior = "auto") {
|
|
229
|
+
const options = { behavior, top: offset };
|
|
230
|
+
this.scrollTo(options);
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Scrolls to the offset for the given index.
|
|
234
|
+
* @param index The index of the element to scroll to.
|
|
235
|
+
* @param behavior The ScrollBehavior to use when scrolling. Default is behavior is `auto`.
|
|
236
|
+
*/
|
|
237
|
+
scrollToIndex(index, behavior = "auto") {
|
|
238
|
+
this._scrollStrategy.scrollToIndex(index, behavior);
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Gets the current scroll offset from the start of the viewport (in pixels).
|
|
242
|
+
* @param from The edge to measure the offset from. Defaults to 'top' in vertical mode and 'start'
|
|
243
|
+
* in horizontal mode.
|
|
244
|
+
*/
|
|
245
|
+
// CHANGES@ANNALIB added override to functions
|
|
246
|
+
measureScrollOffset(from) {
|
|
247
|
+
return from
|
|
248
|
+
? super.measureScrollOffset(from)
|
|
249
|
+
: super.measureScrollOffset("top");
|
|
250
|
+
}
|
|
251
|
+
/** Measure the combined size of all of the rendered items. */
|
|
252
|
+
measureRenderedContentSize() {
|
|
253
|
+
const contentEl = this._contentWrapper.nativeElement;
|
|
254
|
+
return contentEl.offsetHeight;
|
|
255
|
+
}
|
|
256
|
+
/**
|
|
257
|
+
* Measure the total combined size of the given range. Throws if the range includes items that are
|
|
258
|
+
* not rendered.
|
|
259
|
+
*/
|
|
260
|
+
measureRangeSize(range) {
|
|
261
|
+
if (!this._forOf) {
|
|
262
|
+
return 0;
|
|
263
|
+
}
|
|
264
|
+
return this._forOf.measureRangeSize(range, this.orientation);
|
|
265
|
+
}
|
|
266
|
+
/** Update the viewport dimensions and re-render. */
|
|
267
|
+
checkViewportSize() {
|
|
268
|
+
// TODO: Cleanup later when add logic for handling content resize
|
|
269
|
+
this._measureViewportSize();
|
|
270
|
+
this._scrollStrategy.onDataLengthChanged();
|
|
271
|
+
}
|
|
272
|
+
/** Measure the viewport size. */
|
|
273
|
+
_measureViewportSize() {
|
|
274
|
+
const viewportEl = this.elementRef.nativeElement;
|
|
275
|
+
this._viewportSize = viewportEl.clientHeight;
|
|
276
|
+
}
|
|
277
|
+
/** Queue up change detection to run. */
|
|
278
|
+
_markChangeDetectionNeeded(runAfter) {
|
|
279
|
+
if (runAfter) {
|
|
280
|
+
this._runAfterChangeDetection.push(runAfter);
|
|
281
|
+
}
|
|
282
|
+
// Use a Promise to batch together calls to `_doChangeDetection`. This way if we set a bunch of
|
|
283
|
+
// properties sequentially we only have to run `_doChangeDetection` once at the end.
|
|
284
|
+
if (!this._isChangeDetectionPending) {
|
|
285
|
+
this._isChangeDetectionPending = true;
|
|
286
|
+
this.ngZone.runOutsideAngular(() => Promise.resolve().then(() => {
|
|
287
|
+
this._doChangeDetection();
|
|
288
|
+
}));
|
|
289
|
+
}
|
|
290
|
+
}
|
|
291
|
+
/** Run change detection. */
|
|
292
|
+
_doChangeDetection() {
|
|
293
|
+
this._isChangeDetectionPending = false;
|
|
294
|
+
// Apply the content transform. The transform can't be set via an Angular binding because
|
|
295
|
+
// bypassSecurityTrustStyle is banned in Google. However the value is safe, it's composed of
|
|
296
|
+
// string literals, a variable that can only be 'X' or 'Y', and user input that is run through
|
|
297
|
+
// the `Number` function first to coerce it to a numeric value.
|
|
298
|
+
this._contentWrapper.nativeElement.style.top = this._renderedContentTransform;
|
|
299
|
+
// Apply changes to Angular bindings. Note: We must call `markForCheck` to run change detection
|
|
300
|
+
// from the root, since the repeated items are content projected in. Calling `detectChanges`
|
|
301
|
+
// instead does not properly check the projected content.
|
|
302
|
+
this.ngZone.run(() => this._changeDetectorRef.markForCheck());
|
|
303
|
+
const runAfterChangeDetection = this._runAfterChangeDetection;
|
|
304
|
+
this._runAfterChangeDetection = [];
|
|
305
|
+
for (const fn of runAfterChangeDetection) {
|
|
306
|
+
fn();
|
|
307
|
+
}
|
|
308
|
+
}
|
|
309
|
+
/** Calculates the `style.width` and `style.height` for the spacer element. */
|
|
310
|
+
_calculateSpacerSize() {
|
|
311
|
+
this._totalContentHeight = `${this._totalContentSize}px`;
|
|
312
|
+
this._totalContentWidth = "";
|
|
313
|
+
}
|
|
314
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AnnaTableVirtualScrollViewportComponent, deps: [{ token: i0.ElementRef }, { token: i0.ChangeDetectorRef }, { token: i0.NgZone }, { token: VIRTUAL_SCROLL_STRATEGY, optional: true }, { token: i1.Directionality, optional: true }, { token: i2.ScrollDispatcher }, { token: i2.ViewportRuler }, { token: i3.AnnaGtHelperService }], target: i0.ɵɵFactoryTarget.Component }); }
|
|
315
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.2.12", type: AnnaTableVirtualScrollViewportComponent, selector: "anna-table-virtual-scroll-viewport", inputs: { orientation: "orientation" }, outputs: { scrolledIndexChange: "scrolledIndexChange" }, host: { properties: { "class.anna-table-virtual-scroll-orientation-horizontal": "orientation === \"horizontal\"", "class.anna-table-virtual-scroll-orientation-vertical": "orientation !== \"horizontal\"" }, classAttribute: "anna-table-virtual-scroll-viewport" }, providers: [
|
|
316
|
+
{
|
|
317
|
+
provide: CdkScrollable,
|
|
318
|
+
useExisting: AnnaTableVirtualScrollViewportComponent
|
|
319
|
+
},
|
|
320
|
+
{
|
|
321
|
+
provide: CdkVirtualScrollViewport,
|
|
322
|
+
useExisting: AnnaTableVirtualScrollViewportComponent
|
|
323
|
+
}
|
|
324
|
+
], viewQueries: [{ propertyName: "_contentWrapper", first: true, predicate: ["contentWrapper"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<!--\r\n Wrap the rendered content in an element that will be used to offset it based on the scroll\r\n position.\r\n-->\r\n<div #contentWrapper class=\"anna-table-virtual-scroll-content-wrapper\">\r\n\t<ng-content></ng-content>\r\n</div>\r\n<!--\r\n Spacer used to force the scrolling container to the correct size for the *total* number of items\r\n so that the scrollbar captures the size of the entire data set.\r\n-->\r\n<div class=\"app-table-virtual-scroll-spacer\" [style.width]=\"_totalContentWidth\" [style.height]=\"_totalContentHeight\">\r\n</div>", styles: ["anna-table-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict;will-change:scroll-position;-webkit-overflow-scrolling:touch}.anna-table-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .anna-table-virtual-scroll-content-wrapper{right:0;left:auto}.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper{min-height:100%}.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper{min-width:100%}.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.app-table-virtual-scroll-spacer{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0}[dir=rtl] .app-table-virtual-scroll-spacer{right:0;left:auto;transform-origin:100% 0}\n"], changeDetection: i0.ChangeDetectionStrategy.OnPush, encapsulation: i0.ViewEncapsulation.None }); }
|
|
325
|
+
}
|
|
326
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.2.12", ngImport: i0, type: AnnaTableVirtualScrollViewportComponent, decorators: [{
|
|
327
|
+
type: Component,
|
|
328
|
+
args: [{ selector: "anna-table-virtual-scroll-viewport", host: {
|
|
329
|
+
class: "anna-table-virtual-scroll-viewport",
|
|
330
|
+
"[class.anna-table-virtual-scroll-orientation-horizontal]": 'orientation === "horizontal"',
|
|
331
|
+
"[class.anna-table-virtual-scroll-orientation-vertical]": 'orientation !== "horizontal"'
|
|
332
|
+
}, encapsulation: ViewEncapsulation.None, changeDetection: ChangeDetectionStrategy.OnPush, providers: [
|
|
333
|
+
{
|
|
334
|
+
provide: CdkScrollable,
|
|
335
|
+
useExisting: AnnaTableVirtualScrollViewportComponent
|
|
336
|
+
},
|
|
337
|
+
{
|
|
338
|
+
provide: CdkVirtualScrollViewport,
|
|
339
|
+
useExisting: AnnaTableVirtualScrollViewportComponent
|
|
340
|
+
}
|
|
341
|
+
], template: "<!--\r\n Wrap the rendered content in an element that will be used to offset it based on the scroll\r\n position.\r\n-->\r\n<div #contentWrapper class=\"anna-table-virtual-scroll-content-wrapper\">\r\n\t<ng-content></ng-content>\r\n</div>\r\n<!--\r\n Spacer used to force the scrolling container to the correct size for the *total* number of items\r\n so that the scrollbar captures the size of the entire data set.\r\n-->\r\n<div class=\"app-table-virtual-scroll-spacer\" [style.width]=\"_totalContentWidth\" [style.height]=\"_totalContentHeight\">\r\n</div>", styles: ["anna-table-virtual-scroll-viewport{display:block;position:relative;overflow:auto;contain:strict;will-change:scroll-position;-webkit-overflow-scrolling:touch}.anna-table-virtual-scroll-content-wrapper{position:absolute;top:0;left:0;contain:content}[dir=rtl] .anna-table-virtual-scroll-content-wrapper{right:0;left:auto}.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper{min-height:100%}.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-horizontal .anna-table-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-left:0;padding-right:0;margin-left:0;margin-right:0;border-left-width:0;border-right-width:0;outline:none}.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper{min-width:100%}.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>dl:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>ol:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>table:not([cdkVirtualFor]),.app-table-virtual-scroll-orientation-vertical .anna-table-virtual-scroll-content-wrapper>ul:not([cdkVirtualFor]){padding-top:0;padding-bottom:0;margin-top:0;margin-bottom:0;border-top-width:0;border-bottom-width:0;outline:none}.app-table-virtual-scroll-spacer{position:absolute;top:0;left:0;height:1px;width:1px;transform-origin:0 0}[dir=rtl] .app-table-virtual-scroll-spacer{right:0;left:auto;transform-origin:100% 0}\n"] }]
|
|
342
|
+
}], ctorParameters: function () { return [{ type: i0.ElementRef }, { type: i0.ChangeDetectorRef }, { type: i0.NgZone }, { type: undefined, decorators: [{
|
|
343
|
+
type: Optional
|
|
344
|
+
}, {
|
|
345
|
+
type: Inject,
|
|
346
|
+
args: [VIRTUAL_SCROLL_STRATEGY]
|
|
347
|
+
}] }, { type: i1.Directionality, decorators: [{
|
|
348
|
+
type: Optional
|
|
349
|
+
}] }, { type: i2.ScrollDispatcher }, { type: i2.ViewportRuler }, { type: i3.AnnaGtHelperService }]; }, propDecorators: { orientation: [{
|
|
350
|
+
type: Input
|
|
351
|
+
}], scrolledIndexChange: [{
|
|
352
|
+
type: Output
|
|
353
|
+
}], _contentWrapper: [{
|
|
354
|
+
type: ViewChild,
|
|
355
|
+
args: ["contentWrapper", { static: true }]
|
|
356
|
+
}] } });
|
|
357
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYW5uYS10YWJsZS12aXJ0dWFsLXNjcm9sbC12aWV3cG9ydC5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi8uLi8uLi9wcm9qZWN0cy9hbm5hLWNvcmUvc3JjL2xpYi9hbm5hLWdlbmVyaWMtdGFibGUtbGliL2NvbXBvbmVudHMvYW5uYS10YWJsZS12aXJ0dWFsLXNjcm9sbC12aWV3cG9ydC9hbm5hLXRhYmxlLXZpcnR1YWwtc2Nyb2xsLXZpZXdwb3J0LmNvbXBvbmVudC50cyIsIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3Byb2plY3RzL2FubmEtY29yZS9zcmMvbGliL2FubmEtZ2VuZXJpYy10YWJsZS1saWIvY29tcG9uZW50cy9hbm5hLXRhYmxlLXZpcnR1YWwtc2Nyb2xsLXZpZXdwb3J0L2FubmEtdGFibGUtdmlydHVhbC1zY3JvbGwtdmlld3BvcnQuY29tcG9uZW50Lmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUE7Ozs7OztHQU1HO0FBRUYsT0FBTyxFQUFFLGNBQWMsRUFBRSxNQUFNLG1CQUFtQixDQUFDO0FBRW5ELE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsaUJBQWlCLEVBQ2pCLFNBQVMsRUFDVCxVQUFVLEVBQ1YsTUFBTSxFQUNOLEtBQUssRUFDTCxNQUFNLEVBR04sUUFBUSxFQUNSLE1BQU0sRUFDTixTQUFTLEVBQ1QsaUJBQWlCLEVBQ2xCLE1BQU0sZUFBZSxDQUFDO0FBQ3ZCLE9BQU8sRUFDTCx1QkFBdUIsRUFDdkIsYUFBYSxFQUNiLFVBQVUsRUFDVixPQUFPLEVBRVAsWUFBWSxFQUNiLE1BQU0sTUFBTSxDQUFDO0FBQ2QsT0FBTyxFQUFFLFNBQVMsRUFBRSxTQUFTLEVBQUUsU0FBUyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFDakUsT0FBTyxFQUNMLHdCQUF3QixFQUN4QixhQUFhLEVBRWIsdUJBQXVCLEVBRXZCLGdCQUFnQixFQUNoQixhQUFhLEVBRWQsTUFBTSx3QkFBd0IsQ0FB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O2dCQUNFLE9BQU8sRUFBRSxhQUFhO2dCQUN0QixXQUFXLEVBQUUsdUNBQXVDO2FBQ3JEO1lBQ0Q7Z0JBQ0UsT0FBTyxFQUFFLHdCQUF3QjtnQkFDakMsV0FBVyxFQUFFLHVDQUF1QzthQUNyRDtTQUNGLGtMQ3hGSixxakJBWU07OzRGRDhFUSx1Q0FBdUM7a0JBeEJuRCxTQUFTOytCQUNFLG9DQUFvQyxRQUd4Qzt3QkFDSixLQUFLLEVBQUUsb0NBQW9DO3dCQUMzQywwREFBMEQsRUFDeEQsOEJBQThCO3dCQUNoQyx3REFBd0QsRUFDdEQsOEJBQThCO3FCQUNqQyxpQkFDYyxpQkFBaUIsQ0FBQyxJQUFJLG1CQUNwQix1QkFBdUIsQ0FBQyxNQUFNLGFBQ3BDO3dCQUNUOzRCQUNFLE9BQU8sRUFBRSxhQUFhOzRCQUN0QixXQUFXLHlDQUF5Qzt5QkFDckQ7d0JBQ0Q7NEJBQ0UsT0FBTyxFQUFFLHdCQUF3Qjs0QkFDakMsV0FBVyx5Q0FBeUM7eUJBQ3JEO3FCQUNGOzswQkFnR0UsUUFBUTs7MEJBQ1IsTUFBTTsyQkFBQyx1QkFBdUI7OzBCQUU5QixRQUFRO3lJQXZGUCxXQUFXO3NCQURkLEtBQUs7Z0JBaUJJLG1CQUFtQjtzQkFBNUIsTUFBTTtnQkFVd0MsZUFBZTtzQkFBN0QsU0FBUzt1QkFBQyxnQkFBZ0IsRUFBRSxFQUFFLE1BQU0sRUFBRSxJQUFJLEVBQUUiLCJzb3VyY2VzQ29udGVudCI6WyIvKipcclxuICogQGxpY2Vuc2VcclxuICogQ29weXJpZ2h0IEdvb2dsZSBMTEMgQWxsIFJpZ2h0cyBSZXNlcnZlZC5cclxuICpcclxuICogVXNlIG9mIHRoaXMgc291cmNlIGNvZGUgaXMgZ292ZXJuZWQgYnkgYW4gTUlULXN0eWxlIGxpY2Vuc2UgdGhhdCBjYW4gYmVcclxuICogZm91bmQgaW4gdGhlIExJQ0VOU0UgZmlsZSBhdCBodHRwczovL2FuZ3VsYXIuaW8vbGljZW5zZVxyXG4gKi9cclxuXHJcbiBpbXBvcnQgeyBEaXJlY3Rpb25hbGl0eSB9IGZyb20gXCJAYW5ndWxhci9jZGsvYmlkaVwiO1xyXG4gaW1wb3J0IHsgTGlzdFJhbmdlIH0gZnJvbSBcIkBhbmd1bGFyL2Nkay9jb2xsZWN0aW9uc1wiO1xyXG4gaW1wb3J0IHtcclxuICAgQ2hhbmdlRGV0ZWN0aW9uU3RyYXRlZ3ksXHJcbiAgIENoYW5nZURldGVjdG9yUmVmLFxyXG4gICBDb21wb25lbnQsXHJcbiAgIEVsZW1lbnRSZWYsXHJcbiAgIEluamVjdCxcclxuICAgSW5wdXQsXHJcbiAgIE5nWm9uZSxcclxuICAgT25EZXN0cm95LFxyXG4gICBPbkluaXQsXHJcbiAgIE9wdGlvbmFsLFxyXG4gICBPdXRwdXQsXHJcbiAgIFZpZXdDaGlsZCxcclxuICAgVmlld0VuY2Fwc3VsYXRpb25cclxuIH0gZnJvbSBcIkBhbmd1bGFyL2NvcmVcIjtcclxuIGltcG9ydCB7XHJcbiAgIGFuaW1hdGlvbkZyYW1lU2NoZWR1bGVyLFxyXG4gICBhc2FwU2NoZWR1bGVyLFxyXG4gICBPYnNlcnZhYmxlLFxyXG4gICBTdWJqZWN0LFxyXG4gICBPYnNlcnZlcixcclxuICAgU3Vic2NyaXB0aW9uXHJcbiB9IGZyb20gXCJyeGpzXCI7XHJcbiBpbXBvcnQgeyBhdWRpdFRpbWUsIHN0YXJ0V2l0aCwgdGFrZVVudGlsIH0gZnJvbSBcInJ4anMvb3BlcmF0b3JzXCI7XHJcbiBpbXBvcnQge1xyXG4gICBDZGtWaXJ0dWFsU2Nyb2xsVmlld3BvcnQsXHJcbiAgIENka1Njcm9sbGFibGUsXHJcbiAgIENka1ZpcnR1YWxTY3JvbGxSZXBlYXRlcixcclxuICAgVklSVFVBTF9TQ1JPTExfU1RSQVRFR1ksXHJcbiAgIFZpcnR1YWxTY3JvbGxTdHJhdGVneSxcclxuICAgU2Nyb2xsRGlzcGF0Y2hlcixcclxuICAgVmlld3BvcnRSdWxlcixcclxuICAgRXh0ZW5kZWRTY3JvbGxUb09wdGlvbnNcclxuIH0gZnJvbSBcIkBhbmd1bGFyL2Nkay9zY3JvbGxpbmdcIjtcclxuaW1wb3J0IHsgQW5uYUd0SGVscGVyU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL2FubmEtY29yZS1zaGFyZWQtbGliL3NlcnZpY2VzL2FubmEtZ2VuZXJpYy10YWJsZS5zZXJ2aWNlJztcclxuIFxyXG4gLyoqIENoZWNrcyBpZiB0aGUgZ2l2ZW4gcmFuZ2VzIGFyZSBlcXVhbC4gKi9cclxuIGZ1bmN0aW9uIHJhbmdlc0VxdWFsKHIxOiBMaXN0UmFuZ2UsIHIyOiBMaXN0UmFuZ2UpOiBib29sZWFuIHtcclxuICAgcmV0dXJuIHIxLnN0YXJ0ID09IHIyLnN0YXJ0ICYmIHIxLmVuZCA9PSByMi5lbmQ7XHJcbiB9XHJcbiBcclxuIC8qKlxyXG4gICogU2NoZWR1bGVyIHRvIGJlIHVzZWQgZm9yIHNjcm9sbCBldmVudHMuIE5lZWRzIHRvIGZhbGwgYmFjayB0b1xyXG4gICogc29tZXRoaW5nIHRoYXQgZG9lc24ndCByZWx5IG9uIHJlcXVlc3RBbmltYXRpb25GcmFtZSBvbiBlbnZpcm9ubWVudHNcclxuICAqIHRoYXQgZG9uJ3Qgc3VwcG9ydCBpdCAoZS5nLiBzZXJ2ZXItc2lkZSByZW5kZXJpbmcpLlxyXG4gICovXHJcbiBjb25zdCBTQ1JPTExfU0NIRURVTEVSID1cclxuICAgdHlwZW9mIHJlcXVlc3RBbmltYXRpb25GcmFtZSAhPT0gXCJ1bmRlZmluZWRcIlxyXG4gICAgID8gYW5pbWF0aW9uRnJhbWVTY2hlZHVsZXJcclxuICAgICA6IGFzYXBTY2hlZHVsZXI7XHJcbiBcclxuIC8qKlxyXG4gICogQSB2aWV3cG9ydCB0aGF0IHZpcnR1YWxpemVzIGl0cyBzY3JvbGxpbmcgd2l0aCB0aGUgaGVscCBvZiBgQ2RrVmlydHVhbEZvck9mYC5cclxuICAqIFVzZXMgYHRvcDogI3B4YCBpbnN0ZWFkIG9mIGB0cmFuc2Zvcm06IHRyYW5zbGF0ZVkoI3B4KWAgbGlrZSB0aGUgY2RrIHZpcnR1YWwgc2Nyb2xsIHZpZXdwb3J0IGRvZXNcclxuICAqIHdoaWNoIGF2b2lkcyBmbGlja2VyaW5nIG9mIGVsZW1lbnRzIGluIHRoZSB0cmFuc2Zvcm1lZCBjb250YWluZXIgd2l0aCBgcG9zaXRpb246IHN0aWNreWAuXHJcbiAgKi9cclxuIEBDb21wb25lbnQoe1xyXG4gICBzZWxlY3RvcjogXCJhbm5hLXRhYmxlLXZpcnR1YWwtc2Nyb2xsLXZpZXdwb3J0XCIsXHJcbiAgIHRlbXBsYXRlVXJsOiBcImFubmEtdGFibGUtdmlydHVhbC1zY3JvbGwtdmlld3BvcnQuY29tcG9uZW50Lmh0bWxcIixcclxuICAgc3R5bGVVcmxzOiBbXCJhbm5hLXRhYmxlLXZpcnR1YWwtc2Nyb2xsLXZpZXdwb3J0LmNvbXBvbmVudC5zY3NzXCJdLFxyXG4gICBob3N0OiB7XHJcbiAgICAgY2xhc3M6IFwiYW5uYS10YWJsZS12aXJ0dWFsLXNjcm9sbC12aWV3cG9ydFwiLFxyXG4gICAgIFwiW2NsYXNzLmFubmEtdGFibGUtdmlydHVhbC1zY3JvbGwtb3JpZW50YXRpb24taG9yaXpvbnRhbF1cIjpcclxuICAgICAgICdvcmllbnRhdGlvbiA9PT0gXCJob3Jpem9udGFsXCInLFxyXG4gICAgIFwiW2NsYXNzLmFubmEtdGFibGUtdmlydHVhbC1zY3JvbGwtb3JpZW50YXRpb24tdmVydGljYWxdXCI6XHJcbiAgICAgICAnb3JpZW50YXRpb24gIT09IFwiaG9yaXpvbnRhbFwiJ1xyXG4gICB9LFxyXG4gICBlbmNhcHN1bGF0aW9uOiBWaWV3RW5jYXBzdWxhdGlvbi5Ob25lLFxyXG4gICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcclxuICAgcHJvdmlkZXJzOiBbXHJcbiAgICAge1xyXG4gICAgICAgcHJvdmlkZTogQ2RrU2Nyb2xsYWJsZSxcclxuICAgICAgIHVzZUV4aXN0aW5nOiBBbm5hVGFibGVWaXJ0dWFsU2Nyb2xsVmlld3BvcnRDb21wb25lbnRcclxuICAgICB9LFxyXG4gICAgIHtcclxuICAgICAgIHByb3ZpZGU6IENka1ZpcnR1YWxTY3JvbGxWaWV3cG9ydCxcclxuICAgICAgIHVzZUV4aXN0aW5nOiBBbm5hVGFibGVWaXJ0dWFsU2Nyb2xsVmlld3BvcnRDb21wb25lbnRcclxuICAgICB9XHJcbiAgIF1cclxuIH0pXHJcbiBleHBvcnQgY2xhc3MgQW5uYVRhYmxlVmlydHVhbFNjcm9sbFZpZXdwb3J0Q29tcG9uZW50IGV4dGVuZHMgQ2RrU2Nyb2xsYWJsZVxyXG4gICBpbXBsZW1lbnRzIE9uSW5pdCwgT25EZXN0cm95IHtcclxuICAgLyoqIEVtaXRzIHdoZW4gdGhlIHZpZXdwb3J0IGlzIGRldGFjaGVkIGZyb20gYSBDZGtWaXJ0dWFsRm9yT2YuICovXHJcbiAgIHByaXZhdGUgX2RldGFjaGVkU3ViamVjdCA9IG5ldyBTdWJqZWN0PHZvaWQ+KCk7XHJcbiBcclxuICAgLyoqIEVtaXRzIHdoZW4gdGhlIHJlbmRlcmVkIHJhbmdlIGNoYW5nZXMuICovXHJcbiAgIHByaXZhdGUgX3JlbmRlcmVkUmFuZ2VTdWJqZWN0ID0gbmV3IFN1YmplY3Q8TGlzdFJhbmdlPigpO1xyXG4gXHJcbiAgIC8qKiBUaGUgZGlyZWN0aW9uIHRoZSB2aWV3cG9ydCBzY3JvbGxzLiAqL1xyXG4gICBASW5wdXQoKVxyXG4gICBnZXQgb3JpZW50YXRpb24oKSB7XHJcbiAgICAgcmV0dXJuIHRoaXMuX29yaWVudGF0aW9uO1xyXG4gICB9XHJcbiAgIHNldCBvcmllbnRhdGlvbihvcmllbnRhdGlvbjogXCJob3Jpem9udGFsXCIgfCBcInZlcnRpY2FsXCIpIHtcclxuICAgICBpZiAodGhpcy5fb3JpZW50YXRpb24gIT09IG9yaWVudGF0aW9uKSB7XHJcbiAgICAgICB0aGlzLl9vcmllbnRhdGlvbiA9IG9yaWVudGF0aW9uO1xyXG4gICAgICAgdGhpcy5fY2FsY3VsYXRlU3BhY2VyU2l6ZSgpO1xyXG4gICAgIH1cclxuICAgfVxyXG4gICBwcml2YXRlIF9vcmllbnRhdGlvbjogXCJob3Jpem9udGFsXCIgfCBcInZlcnRpY2FsXCIgPSBcInZlcnRpY2FsXCI7XHJcbiBcclxuICAgLy8gTm90ZTogd2UgZG9uJ3QgdXNlIHRoZSB0eXBpY2FsIEV2ZW50RW1pdHRlciBoZXJlIGJlY2F1c2Ugd2UgbmVlZCB0byBzdWJzY3JpYmUgdG8gdGhlIHNjcm9sbFxyXG4gICAvLyBzdHJhdGVneSBsYXppbHkgKGkuZS4gb25seSBpZiB0aGUgdXNlciBpcyBhY3R1YWxseSBsaXN0ZW5pbmcgdG8gdGhlIGV2ZW50cykuIFdlIGRvIHRoaXMgYmVjYXVzZVxyXG4gICAvLyBkZXBlbmRpbmcgb24gaG93IHRoZSBzdHJhdGVneSBjYWxjdWxhdGVzIHRoZSBzY3JvbGxlZCBpbmRleCwgaXQgbWF5IGNvbWUgYXQgYSBjb3N0IHRvXHJcbiAgIC8vIHBlcmZvcm1hbmNlLlxyXG4gICAvKiogRW1pdHMgd2hlbiB0aGUgaW5kZXggb2YgdGhlIGZpcnN0IGVsZW1lbnQgdmlzaWJsZSBpbiB0aGUgdmlld3BvcnQgY2hhbmdlcy4gKi9cclxuICAgQE91dHB1dCgpIHNjcm9sbGVkSW5kZXhDaGFuZ2U6IE9ic2VydmFibGU8bnVtYmVyPiA9IG5ldyBPYnNlcnZhYmxlKFxyXG4gICAgIChvYnNlcnZlcjogT2JzZXJ2ZXI8bnVtYmVyPikgPT5cclxuICAgICAgIHRoaXMuX3Njcm9sbFN0cmF0ZWd5LnNjcm9sbGVkSW5kZXhDaGFuZ2Uuc3Vic2NyaWJlKGluZGV4ID0+XHJcbiAgICAgICAgIFByb21pc2UucmVzb2x2ZSgpLnRoZW4oKCkgPT5cclxuICAgICAgICAgICB0aGlzLm5nWm9uZS5ydW4oKCkgPT4gb2JzZXJ2ZXIubmV4dChpbmRleCkpXHJcbiAgICAgICAgIClcclxuICAgICAgIClcclxuICAgKTtcclxuIFxyXG4gICAvKiogVGhlIGVsZW1lbnQgdGhhdCB3cmFwcyB0aGUgcmVuZGVyZWQgY29udGVudC4gKi9cclxuICAgQFZpZXdDaGlsZChcImNvbnRlbnRXcmFwcGVyXCIsIHsgc3RhdGljOiB0cnVlIH0pIF9jb250ZW50V3JhcHBlcjogRWxlbWVudFJlZjxcclxuICAgICBIVE1MRWxlbWVudFxyXG4gICA+O1xyXG4gXHJcbiAgIC8qKiBBIHN0cmVhbSB0aGF0IGVtaXRzIHdoZW5ldmVyIHRoZSByZW5kZXJlZCByYW5nZSBjaGFuZ2VzLiAqL1xyXG4gICByZW5kZXJlZFJhbmdlU3RyZWFtOiBPYnNlcnZhYmxlPExpc3RSYW5nZT4gPSB0aGlzLl9yZW5kZXJlZFJhbmdlU3ViamVjdDtcclxuIFxyXG4gICAvKipcclxuICAgICogVGhlIHRvdGFsIHNpemUgb2YgYWxsIGNvbnRlbnQgKGluIHBpeGVscyksIGluY2x1ZGluZyBjb250ZW50IHRoYXQgaXMgbm90IGN1cnJlbnRseSByZW5kZXJlZC5cclxuICAgICovXHJcbiAgIHByaXZhdGUgX3RvdGFsQ29udGVudFNpemUgPSAwO1xyXG4gXHJcbiAgIC8qKiBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGBzdHlsZS53aWR0aGAgcHJvcGVydHkgdmFsdWUgdG8gYmUgdXNlZCBmb3IgdGhlIHNwYWNlciBlbGVtZW50LiAqL1xyXG4gICBfdG90YWxDb250ZW50V2lkdGggPSBcIlwiO1xyXG4gXHJcbiAgIC8qKiBBIHN0cmluZyByZXByZXNlbnRpbmcgdGhlIGBzdHlsZS5oZWlnaHRgIHByb3BlcnR5IHZhbHVlIHRvIGJlIHVzZWQgZm9yIHRoZSBzcGFjZXIgZWxlbWVudC4gKi9cclxuICAgX3RvdGFsQ29udGVudEhlaWdodCA9IFwiXCI7XHJcbiBcclxuICAgLyoqXHJcbiAgICAqIFRoZSBDU1MgdHJhbnNmb3JtIGFwcGxpZWQgdG8gdGhlIHJlbmRlcmVkIHN1YnNldCBvZiBpdGVtcyBzbyB0aGF0IHRoZXkgYXBwZWFyIHdpdGhpbiB0aGUgYm91bmRzXHJcbiAgICAqIG9mIHRoZSB2aXNpYmxlIHZpZXdwb3J0LlxyXG4gICAgKi9cclxuICAgcHJpdmF0ZSBfcmVuZGVyZWRDb250ZW50VHJhbnNmb3JtOiBzdHJpbmc7XHJcbiBcclxuICAgLyoqIFRoZSBjdXJyZW50bHkgcmVuZGVyZWQgcmFuZ2Ugb2YgaW5kaWNlcy4gKi9cclxuICAgcHJpdmF0ZSBfcmVuZGVyZWRSYW5nZTogTGlzdFJhbmdlID0geyBzdGFydDogMCwgZW5kOiAwIH07XHJcbiBcclxuICAgLyoqIFRoZSBsZW5ndGggb2YgdGhlIGRhdGEgYm91bmQgdG8gdGhpcyB2aWV3cG9ydCAoaW4gbnVtYmVyIG9mIGl0ZW1zKS4gKi9cclxuICAgcHJpdmF0ZSBfZGF0YUxlbmd0aCA9IDA7XHJcbiBcclxuICAgLyoqIFRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydCAoaW4gcGl4ZWxzKS4gKi9cclxuICAgcHJpdmF0ZSBfdmlld3BvcnRTaXplID0gMDtcclxuIFxyXG4gICAvKiogdGhlIGN1cnJlbnRseSBhdHRhY2hlZCBDZGtWaXJ0dWFsU2Nyb2xsUmVwZWF0ZXIuICovXHJcbiAgIHByaXZhdGUgX2Zvck9mOiBDZGtWaXJ0dWFsU2Nyb2xsUmVwZWF0ZXI8YW55PiB8IG51bGw7XHJcbiBcclxuICAgLyoqIFRoZSBsYXN0IHJlbmRlcmVkIGNvbnRlbnQgb2Zmc2V0IHRoYXQgd2FzIHNldC4gKi9cclxuICAgcHJpdmF0ZSBfcmVuZGVyZWRDb250ZW50T2Zmc2V0ID0gMDtcclxuIFxyXG4gICAvKipcclxuICAgICogV2hldGhlciB0aGUgbGFzdCByZW5kZXJlZCBjb250ZW50IG9mZnNldCB3YXMgdG8gdGhlIGVuZCBvZiB0aGUgY29udGVudCAoYW5kIHRoZXJlZm9yZSBuZWVkcyB0b1xyXG4gICAgKiBiZSByZXdyaXR0ZW4gYXMgYW4gb2Zmc2V0IHRvIHRoZSBzdGFydCBvZiB0aGUgY29udGVudCkuXHJcbiAgICAqL1xyXG4gICBwcml2YXRlIF9yZW5kZXJlZENvbnRlbnRPZmZzZXROZWVkc1Jld3JpdGUgPSBmYWxzZTtcclxuIFxyXG4gICAvKiogV2hldGhlciB0aGVyZSBpcyBhIHBlbmRpbmcgY2hhbmdlIGRldGVjdGlvbiBjeWNsZS4gKi9cclxuICAgcHJpdmF0ZSBfaXNDaGFuZ2VEZXRlY3Rpb25QZW5kaW5nID0gZmFsc2U7XHJcbiBcclxuICAgLyoqIEEgbGlzdCBvZiBmdW5jdGlvbnMgdG8gcnVuIGFmdGVyIHRoZSBuZXh0IGNoYW5nZSBkZXRlY3Rpb24gY3ljbGUuICovXHJcbiAgIHByaXZhdGUgX3J1bkFmdGVyQ2hhbmdlRGV0ZWN0aW9uOiBGdW5jdGlvbltdID0gW107XHJcbiBcclxuICAgLyoqIFN1YnNjcmlwdGlvbiB0byBjaGFuZ2VzIGluIHRoZSB2aWV3cG9ydCBzaXplLiAqL1xyXG4gICBwcml2YXRlIF92aWV3cG9ydENoYW5nZXMgPSBTdWJzY3JpcHRpb24uRU1QVFk7XHJcbiBcclxuICAgY29uc3RydWN0b3IoXHJcbiAgICAgcHVibGljIG92ZXJyaWRlIGVsZW1lbnRSZWY6IEVsZW1lbnRSZWY8SFRNTEVsZW1lbnQ+LFxyXG4gICAgIHByaXZhdGUgX2NoYW5nZURldGVjdG9yUmVmOiBDaGFuZ2VEZXRlY3RvclJlZixcclxuICAgICBuZ1pvbmU6IE5nWm9uZSxcclxuICAgICBAT3B0aW9uYWwoKVxyXG4gICAgIEBJbmplY3QoVklSVFVBTF9TQ1JPTExfU1RSQVRFR1kpXHJcbiAgICAgcHJpdmF0ZSBfc2Nyb2xsU3RyYXRlZ3k6IFZpcnR1YWxTY3JvbGxTdHJhdGVneSxcclxuICAgICBAT3B0aW9uYWwoKSBkaXI6IERpcmVjdGlvbmFsaXR5LFxyXG4gICAgIHNjcm9sbERpc3BhdGNoZXI6IFNjcm9sbERpc3BhdGNoZXIsXHJcbiAgICAgdmlld3BvcnRSdWxlcjogVmlld3BvcnRSdWxlcixcclxuICAgICBwcml2YXRlIGFubmFHdFNlcnZpY2U6IEFubmFHdEhlbHBlclNlcnZpY2VcclxuICAgKSB7XHJcbiAgICAgc3VwZXIoZWxlbWVudFJlZiwgc2Nyb2xsRGlzcGF0Y2hlciwgbmdab25lLCBkaXIpO1xyXG4gXHJcbiAgICAgaWYgKCFfc2Nyb2xsU3RyYXRlZ3kpIHtcclxuICAgICAgIHRocm93IEVycm9yKFxyXG4gICAgICAgICAnRXJyb3I6IGNkay12aXJ0dWFsLXNjcm9sbC12aWV3cG9ydCByZXF1aXJlcyB0aGUgXCJpdGVtU2l6ZVwiIHByb3BlcnR5IHRvIGJlIHNldC4nXHJcbiAgICAgICApO1xyXG4gICAgIH1cclxuIFxyXG4gICAgIHRoaXMuX3ZpZXdwb3J0Q2hhbmdlcyA9IHZpZXdwb3J0UnVsZXIuY2hhbmdlKCkuc3Vic2NyaWJlKCgpID0+IHtcclxuICAgICAgIHRoaXMuY2hlY2tWaWV3cG9ydFNpemUoKTtcclxuICAgICB9KTtcclxuICAgfVxyXG4gXHJcbiAgIG92ZXJyaWRlIG5nT25Jbml0KCkge1xyXG4gICAgIHN1cGVyLm5nT25Jbml0KCk7XHJcbiBcclxuICAgICAvLyBJdCdzIHN0aWxsIHRvbyBlYXJseSB0byBtZWFzdXJlIHRoZSB2aWV3cG9ydCBhdCB0aGlzIHBvaW50LiBEZWZlcnJpbmcgd2l0aCBhIHByb21pc2UgYWxsb3dzXHJcbiAgICAgLy8gdGhlIFZpZXdwb3J0IHRvIGJlIHJlbmRlcmVkIHdpdGggdGhlIGNvcnJlY3Qgc2l6ZSBiZWZvcmUgd2UgbWVhc3VyZS4gV2UgcnVuIHRoaXMgb3V0c2lkZSB0aGVcclxuICAgICAvLyB6b25lIHRvIGF2b2lkIGNhdXNpbmcgbW9yZSBjaGFuZ2UgZGV0ZWN0aW9uIGN5Y2xlcy4gV2UgaGFuZGxlIHRoZSBjaGFuZ2UgZGV0ZWN0aW9uIGxvb3BcclxuICAgICAvLyBvdXJzZWx2ZXMgaW5zdGVhZC5cclxuICAgICB0aGlzLm5nWm9uZS5ydW5PdXRzaWRlQW5ndWxhcigoKSA9PlxyXG4gICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgIHRoaXMuX21lYXN1cmVWaWV3cG9ydFNpemUoKTtcclxuICAgICAgICAgdGhpcy5fc2Nyb2xsU3RyYXRlZ3kuYXR0YWNoKHRoaXMgYXMgYW55KTtcclxuIFxyXG4gICAgICAgICB0aGlzLmVsZW1lbnRTY3JvbGxlZCgpXHJcbiAgICAgICAgICAgLnBpcGUoXHJcbiAgICAgICAgICAgICAvLyBTdGFydCBvZmYgd2l0aCBhIGZha2Ugc2Nyb2xsIGV2ZW50IHNvIHdlIHByb3Blcmx5IGRldGVjdCBvdXIgaW5pdGlhbCBwb3NpdGlvbi5cclxuICAgICAgICAgICAgIHN0YXJ0V2l0aChudWxsKSxcclxuICAgICAgICAgICAgIC8vIENvbGxlY3QgbXVsdGlwbGUgZXZlbnRzIGludG8gb25lIHVudGlsIHRoZSBuZXh0IGFuaW1hdGlvbiBmcmFtZS4gVGhpcyB3YXkgaWZcclxuICAgICAgICAgICAgIC8vIHRoZXJlIGFyZSBtdWx0aXBsZSBzY3JvbGwgZXZlbnRzIGluIHRoZSBzYW1lIGZyYW1lIHdlIG9ubHkgbmVlZCB0byByZWNoZWNrXHJcbiAgICAgICAgICAgICAvLyBvdXIgbGF5b3V0IG9uY2UuXHJcbiAgICAgICAgICAgICBhdWRpdFRpbWUoMCwgU0NST0xMX1NDSEVEVUxFUilcclxuICAgICAgICAgICApXHJcbiAgICAgICAgICAgLnN1YnNjcmliZSgoKSA9PiB7IHRoaXMuX3Njcm9sbFN0cmF0ZWd5Lm9uQ29udGVudFNjcm9sbGVkKCk7IHRoaXMuYW5uYUd0U2VydmljZS52aXJ0dWFsU2Nyb2xsU3ViamVjdC5uZXh0KHRydWUpO30pO1xyXG4gXHJcbiAgICAgICAgIHRoaXMuX21hcmtDaGFuZ2VEZXRlY3Rpb25OZWVkZWQoKTtcclxuICAgICAgIH0pXHJcbiAgICAgKTtcclxuICAgfVxyXG4gXHJcbiAgIG92ZXJyaWRlIG5nT25EZXN0cm95KCkge1xyXG4gICAgIHRoaXMuZGV0YWNoKCk7XHJcbiAgICAgdGhpcy5fc2Nyb2xsU3RyYXRlZ3kuZGV0YWNoKCk7XHJcbiBcclxuICAgICAvLyBDb21wbGV0ZSBhbGwgc3ViamVjdHNcclxuICAgICB0aGlzLl9yZW5kZXJlZFJhbmdlU3ViamVjdC5jb21wbGV0ZSgpO1xyXG4gICAgIHRoaXMuX2RldGFjaGVkU3ViamVjdC5jb21wbGV0ZSgpO1xyXG4gICAgIHRoaXMuX3ZpZXdwb3J0Q2hhbmdlcy51bnN1YnNjcmliZSgpO1xyXG4gXHJcbiAgICAgc3VwZXIubmdPbkRlc3Ryb3koKTtcclxuICAgfVxyXG4gXHJcbiAgIC8qKiBBdHRhY2hlcyBhIGBDZGtWaXJ0dWFsU2Nyb2xsUmVwZWF0ZXJgIHRvIHRoaXMgdmlld3BvcnQuICovXHJcbiAgIGF0dGFjaChmb3JPZjogQ2RrVmlydHVhbFNjcm9sbFJlcGVhdGVyPGFueT4pIHtcclxuICAgICBpZiAodGhpcy5fZm9yT2YpIHtcclxuICAgICAgIHRocm93IEVycm9yKFwiQ2RrVmlydHVhbFNjcm9sbFZpZXdwb3J0IGlzIGFscmVhZHkgYXR0YWNoZWQuXCIpO1xyXG4gICAgIH1cclxuIFxyXG4gICAgIC8vIFN1YnNjcmliZSB0byB0aGUgZGF0YSBzdHJlYW0gb2YgdGhlIENka1ZpcnR1YWxGb3JPZiB0byBrZWVwIHRyYWNrIG9mIHdoZW4gdGhlIGRhdGEgbGVuZ3RoXHJcbiAgICAgLy8gY2hhbmdlcy4gUnVuIG91dHNpZGUgdGhlIHpvbmUgdG8gYXZvaWQgdHJpZ2dlcmluZyBjaGFuZ2UgZGV0ZWN0aW9uLCBzaW5jZSB3ZSdyZSBtYW5hZ2luZyB0aGVcclxuICAgICAvLyBjaGFuZ2UgZGV0ZWN0aW9uIGxvb3Agb3Vyc2VsdmVzLlxyXG4gICAgIHRoaXMubmdab25lLnJ1bk91dHNpZGVBbmd1bGFyKCgpID0+IHtcclxuICAgICAgIHRoaXMuX2Zvck9mID0gZm9yT2Y7XHJcbiAgICAgICB0aGlzLl9mb3JPZi5kYXRhU3RyZWFtXHJcbiAgICAgICAgIC5waXBlKHRha2VVbnRpbCh0aGlzLl9kZXRhY2hlZFN1YmplY3QpKVxyXG4gICAgICAgICAuc3Vic2NyaWJlKGRhdGEgPT4ge1xyXG4gICAgICAgICAgIGNvbnN0IG5ld0xlbmd0aCA9IGRhdGEubGVuZ3RoO1xyXG4gICAgICAgICAgIGlmIChuZXdMZW5ndGggIT09IHRoaXMuX2RhdGFMZW5ndGgpIHtcclxuICAgICAgICAgICAgIHRoaXMuX2RhdGFMZW5ndGggPSBuZXdMZW5ndGg7XHJcbiAgICAgICAgICAgICB0aGlzLl9zY3JvbGxTdHJhdGVneS5vbkRhdGFMZW5ndGhDaGFuZ2VkKCk7XHJcbiAgICAgICAgICAgfVxyXG4gICAgICAgICAgIHRoaXMuX2RvQ2hhbmdlRGV0ZWN0aW9uKCk7XHJcbiAgICAgICAgIH0pO1xyXG4gICAgIH0pO1xyXG4gICB9XHJcbiBcclxuICAgLyoqIERldGFjaGVzIHRoZSBjdXJyZW50IGBDZGtWaXJ0dWFsRm9yT2ZgLiAqL1xyXG4gICBkZXRhY2goKSB7XHJcbiAgICAgdGhpcy5fZm9yT2YgPSBudWxsO1xyXG4gICAgIHRoaXMuX2RldGFjaGVkU3ViamVjdC5uZXh0KCk7XHJcbiAgIH1cclxuIFxyXG4gICAvKiogR2V0cyB0aGUgbGVuZ3RoIG9mIHRoZSBkYXRhIGJvdW5kIHRvIHRoaXMgdmlld3BvcnQgKGluIG51bWJlciBvZiBpdGVtcykuICovXHJcbiAgIGdldERhdGFMZW5ndGgoKTogbnVtYmVyIHtcclxuICAgICByZXR1cm4gdGhpcy5fZGF0YUxlbmd0aDtcclxuICAgfVxyXG4gXHJcbiAgIC8qKiBHZXRzIHRoZSBzaXplIG9mIHRoZSB2aWV3cG9ydCAoaW4gcGl4ZWxzKS4gKi9cclxuICAgZ2V0Vmlld3BvcnRTaXplKCk6IG51bWJlciB7XHJcbiAgICAgcmV0dXJuIHRoaXMuX3ZpZXdwb3J0U2l6ZTtcclxuICAgfVxyXG4gXHJcbiAgIC8vIFRPRE8obW1hbGVyYmEpOiBUaGlzIGlzIHRlY2huaWNhbGx5IG91dCBvZiBzeW5jIHdpdGggd2hhdCdzIHJlYWxseSByZW5kZXJlZCB1bnRpbCBhIHJlbmRlclxyXG4gICAvLyBjeWNsZSBoYXBwZW5zLiBJJ20gYmVpbmcgY2FyZWZ1bCB0byBvbmx5IGNhbGwgaXQgYWZ0ZXIgdGhlIHJlbmRlciBjeWNsZSBpcyBjb21wbGV0ZSBhbmQgYmVmb3JlXHJcbiAgIC8vIHNldHRpbmcgaXQgdG8gc29tZXRoaW5nIGVsc2UsIGJ1dCBpdHMgZXJyb3IgcHJvbmUgYW5kIHNob3VsZCBwcm9iYWJseSBiZSBzcGxpdCBpbnRvXHJcbiAgIC8vIGBwZW5kaW5nUmFuZ2VgIGFuZCBgcmVuZGVyZWRSYW5nZWAsIHRoZSBsYXR0ZXIgcmVmbGVjdGluZyB3aGF0cyBhY3R1YWxseSBpbiB0aGUgRE9NLlxyXG4gXHJcbiAgIC8qKiBHZXQgdGhlIGN1cnJlbnQgcmVuZGVyZWQgcmFuZ2Ugb2YgaXRlbXMuICovXHJcbiAgIGdldFJlbmRlcmVkUmFuZ2UoKTogTGlzdFJhbmdlIHtcclxuICAgICByZXR1cm4gdGhpcy5fcmVuZGVyZWRSYW5nZTtcclxuICAgfVxyXG4gXHJcbiAgIC8qKlxyXG4gICAgKiBTZXRzIHRoZSB0b3RhbCBzaXplIG9mIGFsbCBjb250ZW50IChpbiBwaXhlbHMpLCBpbmNsdWRpbmcgY29udGVudCB0aGF0IGlzIG5vdCBjdXJyZW50bHlcclxuICAgICogcmVuZGVyZWQuXHJcbiAgICAqL1xyXG4gICBzZXRUb3RhbENvbnRlbnRTaXplKHNpemU6IG51bWJlcikge1xyXG4gICAgIGlmICh0aGlzLl90b3RhbENvbnRlbnRTaXplICE9PSBzaXplKSB7XHJcbiAgICAgICB0aGlzLl90b3RhbENvbnRlbnRTaXplID0gc2l6ZTtcclxuICAgICAgIHRoaXMuX2NhbGN1bGF0ZVNwYWNlclNpemUoKTtcclxuICAgICAgIHRoaXMuX21hcmtDaGFuZ2VEZXRlY3Rpb25OZWVkZWQoKTtcclxuICAgICB9XHJcbiAgIH1cclxuIFxyXG4gICAvKiogU2V0cyB0aGUgY3VycmVudGx5IHJlbmRlcmVkIHJhbmdlIG9mIGluZGljZXMuICovXHJcbiAgIHNldFJlbmRlcmVkUmFuZ2UocmFuZ2U6IExpc3RSYW5nZSkge1xyXG4gICAgIGlmICghcmFuZ2VzRXF1YWwodGhpcy5fcmVuZGVyZWRSYW5nZSwgcmFuZ2UpKSB7XHJcbiAgICAgICB0aGlzLl9yZW5kZXJlZFJhbmdlU3ViamVjdC5uZXh0KCh0aGlzLl9yZW5kZXJlZFJhbmdlID0gcmFuZ2UpKTtcclxuICAgICAgIHRoaXMuX21hcmtDaGFuZ2VEZXRlY3Rpb25OZWVkZWQoKCkgPT5cclxuICAgICAgICAgdGhpcy5fc2Nyb2xsU3RyYXRlZ3kub25Db250ZW50UmVuZGVyZWQoKVxyXG4gICAgICAgKTtcclxuICAgICB9XHJcbiAgIH1cclxuIFxyXG4gICAvKipcclxuICAgICogR2V0cyB0aGUgb2Zmc2V0IGZyb20gdGhlIHN0YXJ0IG9mIHRoZSB2aWV3cG9ydCB0byB0aGUgc3RhcnQgb2YgdGhlIHJlbmRlcmVkIGRhdGEgKGluIHBpeGVscykuXHJcbiAgICAqL1xyXG4gICBnZXRPZmZzZXRUb1JlbmRlcmVkQ29udGVudFN0YXJ0KCk6IG51bWJlciB8IG51bGwge1xyXG4gICAgIHJldHVybiB0aGlzLl9yZW5kZXJlZENvbnRlbnRPZmZzZXROZWVkc1Jld3JpdGVcclxuICAgICAgID8gbnVsbFxyXG4gICAgICAgOiB0aGlzLl9yZW5kZXJlZENvbnRlbnRPZmZzZXQ7XHJcbiAgIH1cclxuIFxyXG4gICAvKipcclxuICAgICogU2V0cyB0aGUgb2Zmc2V0IGZyb20gdGhlIHN0YXJ0IG9mIHRoZSB2aWV3cG9ydCB0byBlaXRoZXIgdGhlIHN0YXJ0IG9yIGVuZCBvZiB0aGUgcmVuZGVyZWQgZGF0YVxyXG4gICAgKiAoaW4gcGl4ZWxzKS5cclxuICAgICovXHJcbiAgIHNldFJlbmRlcmVkQ29udGVudE9mZnNldChvZmZzZXQ6IG51bWJlcikge1xyXG4gICAgIGxldCB0b3AgPSBgJHtOdW1iZXIob2Zmc2V0KX1weGA7XHJcbiAgICAgdGhpcy5fcmVuZGVyZWRDb250ZW50T2Zmc2V0ID0gb2Zmc2V0O1xyXG4gICAgIGlmICh0aGlzLl9yZW5kZXJlZENvbnRlbnRUcmFuc2Zvcm0gIT0gdG9wKSB7XHJcbiAgICAgICAvLyBXZSBrbm93IHRoaXMgdmFsdWUgaXMgc2FmZSBiZWNhdXNlIHdlIHBhcnNlIGBvZmZzZXRgIHdpdGggYE51bWJlcigpYCBiZWZvcmUgcGFzc2luZyBpdFxyXG4gICAgICAgLy8gaW50byB0aGUgc3RyaW5nLlxyXG4gICAgICAgdGhpcy5fcmVuZGVyZWRDb250ZW50VHJhbnNmb3JtID0gdG9wO1xyXG4gICAgICAgdGhpcy5fbWFya0NoYW5nZURldGVjdGlvbk5lZWRlZCgoKSA9PiB7XHJcbiAgICAgICAgIGlmICh0aGlzLl9yZW5kZXJlZENvbnRlbnRPZmZzZXROZWVkc1Jld3JpdGUpIHtcclxuICAgICAgICAgICB0aGlzLl9yZW5kZXJlZENvbnRlbnRPZmZzZXQgLT0gdGhpcy5tZWFzdXJlUmVuZGVyZWRDb250ZW50U2l6ZSgpO1xyXG4gICAgICAgICAgIHRoaXMuX3JlbmRlcmVkQ29udGVudE9mZnNldE5lZWRzUmV3cml0ZSA9IGZhbHNlO1xyXG4gICAgICAgICAgIHRoaXMuc2V0UmVuZGVyZWRDb250ZW50T2Zmc2V0KHRoaXMuX3JlbmRlcmVkQ29udGVudE9mZnNldCk7XHJcbiAgICAgICAgIH0gZWxzZSB7XHJcbiAgICAgICAgICAgdGhpcy5fc2Nyb2xsU3RyYXRlZ3kub25SZW5kZXJlZE9mZnNldENoYW5nZWQoKTtcclxuICAgICAgICAgfVxyXG4gICAgICAgfSk7XHJcbiAgICAgfVxyXG4gICB9XHJcbiBcclxuICAgLyoqXHJcbiAgICAqIFNjcm9sbHMgdG8gdGhlIGdpdmVuIG9mZnNldCBmcm9tIHRoZSBzdGFydCBvZiB0aGUgdmlld3BvcnQuIFBsZWFzZSBub3RlIHRoYXQgdGhpcyBpcyBub3QgYWx3YXlzXHJcbiAgICAqIHRoZSBzYW1lIGFzIHNldHRpbmcgYHNjcm9sbFRvcGAgb3IgYHNjcm9sbExlZnRgLiBJbiBhIGhvcml6b250YWwgdmlld3BvcnQgd2l0aCByaWdodC10by1sZWZ0XHJcbiAgICAqIGRpcmVjdGlvbiwgdGhpcyB3b3VsZCBiZSB0aGUgZXF1aXZhbGVudCBvZiBzZXR0aW5nIGEgZmljdGlvbmFsIGBzY3JvbGxSaWdodGAgcHJvcGVydHkuXHJcbiAgICAqIEBwYXJhbSBvZmZzZXQgVGhlIG9mZnNldCB0byBzY3JvbGwgdG8uXHJcbiAgICAqIEBwYXJhbSBiZWhhdmlvciBUaGUgU2Nyb2xsQmVoYXZpb3IgdG8gdXNlIHdoZW4gc2Nyb2xsaW5nLiBEZWZhdWx0IGlzIGJlaGF2aW9yIGlzIGBhdXRvYC5cclxuICAgICovXHJcbiAgIHNjcm9sbFRvT2Zmc2V0KG9mZnNldDogbnVtYmVyLCBiZWhhdmlvcjogU2Nyb2xsQmVoYXZpb3IgPSBcImF1dG9cIikge1xyXG4gICAgIGNvbnN0IG9wdGlvbnM6IEV4dGVuZGVkU2Nyb2xsVG9PcHRpb25zID0geyBiZWhhdmlvciwgdG9wOiBvZmZzZXQgfTtcclxuICAgICB0aGlzLnNjcm9sbFRvKG9wdGlvbnMpO1xyXG4gICB9XHJcbiBcclxuICAgLyoqXHJcbiAgICAqIFNjcm9sbHMgdG8gdGhlIG9mZnNldCBmb3IgdGhlIGdpdmVuIGluZGV4LlxyXG4gICAgKiBAcGFyYW0gaW5kZXggVGhlIGluZGV4IG9mIHRoZSBlbGVtZW50IHRvIHNjcm9sbCB0by5cclxuICAgICogQHBhcmFtIGJlaGF2aW9yIFRoZSBTY3JvbGxCZWhhdmlvciB0byB1c2Ugd2hlbiBzY3JvbGxpbmcuIERlZmF1bHQgaXMgYmVoYXZpb3IgaXMgYGF1dG9gLlxyXG4gICAgKi9cclxuICAgc2Nyb2xsVG9JbmRleChpbmRleDogbnVtYmVyLCBiZWhhdmlvcjogU2Nyb2xsQmVoYXZpb3IgPSBcImF1dG9cIikge1xyXG4gICAgIHRoaXMuX3Njcm9sbFN0cmF0ZWd5LnNjcm9sbFRvSW5kZXgoaW5kZXgsIGJlaGF2aW9yKTtcclxuICAgfVxyXG4gXHJcbiAgIC8qKlxyXG4gICAgKiBHZXRzIHRoZSBjdXJyZW50IHNjcm9sbCBvZmZzZXQgZnJvbSB0aGUgc3RhcnQgb2YgdGhlIHZpZXdwb3J0IChpbiBwaXhlbHMpLlxyXG4gICAgKiBAcGFyYW0gZnJvbSBUaGUgZWRnZSB0byBtZWFzdXJlIHRoZSBvZmZzZXQgZnJvbS4gRGVmYXVsdHMgdG8gJ3RvcCcgaW4gdmVydGljYWwgbW9kZSBhbmQgJ3N0YXJ0J1xyXG4gICAgKiAgICAgaW4gaG9yaXpvbnRhbCBtb2RlLlxyXG4gICAgKi9cclxuICAvLyAgQ0hBTkdFU0BBTk5BTElCIGFkZGVkIG92ZXJyaWRlIHRvIGZ1bmN0aW9uc1xyXG4gICBvdmVycmlkZSBtZWFzdXJlU2Nyb2xsT2Zmc2V0KFxyXG4gICAgIGZyb20/OiBcInRvcFwiIHwgXCJsZWZ0XCIgfCBcInJpZ2h0XCIgfCBcImJvdHRvbVwiIHwgXCJzdGFydFwiIHwgXCJlbmRcIlxyXG4gICApOiBudW1iZXIge1xyXG4gICAgIHJldHVybiBmcm9tXHJcbiAgICAgICA/IHN1cGVyLm1lYXN1cmVTY3JvbGxPZmZzZXQoZnJvbSlcclxuICAgICAgIDogc3VwZXIubWVhc3VyZVNjcm9sbE9mZnNldChcInRvcFwiKTtcclxuICAgfVxyXG4gXHJcbiAgIC8qKiBNZWFzdXJlIHRoZSBjb21iaW5lZCBzaXplIG9mIGFsbCBvZiB0aGUgcmVuZGVyZWQgaXRlbXMuICovXHJcbiAgIG1lYXN1cmVSZW5kZXJlZENvbnRlbnRTaXplKCk6IG51bWJlciB7XHJcbiAgICAgY29uc3QgY29udGVudEVsID0gdGhpcy5fY29udGVudFdyYXBwZXIubmF0aXZlRWxlbWVudDtcclxuICAgICByZXR1cm4gY29udGVudEVsLm9mZnNldEhlaWdodDtcclxuICAgfVxyXG4gXHJcbiAgIC8qKlxyXG4gICAgKiBNZWFzdXJlIHRoZSB0b3RhbCBjb21iaW5lZCBzaXplIG9mIHRoZSBnaXZlbiByYW5nZS4gVGhyb3dzIGlmIHRoZSByYW5nZSBpbmNsdWRlcyBpdGVtcyB0aGF0IGFyZVxyXG4gICAgKiBub3QgcmVuZGVyZWQuXHJcbiAgICAqL1xyXG4gICBtZWFzdXJlUmFuZ2VTaXplKHJhbmdlOiBMaXN0UmFuZ2UpOiBudW1iZXIge1xyXG4gICAgIGlmICghdGhpcy5fZm9yT2YpIHtcclxuICAgICAgIHJldHVybiAwO1xyXG4gICAgIH1cclxuICAgICByZXR1cm4gdGhpcy5fZm9yT2YubWVhc3VyZVJhbmdlU2l6ZShyYW5nZSwgdGhpcy5vcmllbnRhdGlvbik7XHJcbiAgIH1cclxuIFxyXG4gICAvKiogVXBkYXRlIHRoZSB2aWV3cG9ydCBkaW1lbnNpb25zIGFuZCByZS1yZW5kZXIuICovXHJcbiAgIGNoZWNrVmlld3BvcnRTaXplKCkge1xyXG4gICAgIC8vIFRPRE86IENsZWFudXAgbGF0ZXIgd2hlbiBhZGQgbG9naWMgZm9yIGhhbmRsaW5nIGNvbnRlbnQgcmVzaXplXHJcbiAgICAgdGhpcy5fbWVhc3VyZVZpZXdwb3J0U2l6ZSgpO1xyXG4gICAgIHRoaXMuX3Njcm9sbFN0cmF0ZWd5Lm9uRGF0YUxlbmd0aENoYW5nZWQoKTtcclxuICAgfVxyXG4gXHJcbiAgIC8qKiBNZWFzdXJlIHRoZSB2aWV3cG9ydCBzaXplLiAqL1xyXG4gICBwcml2YXRlIF9tZWFzdXJlVmlld3BvcnRTaXplKCkge1xyXG4gICAgIGNvbnN0IHZpZXdwb3J0RWwgPSB0aGlzLmVsZW1lbnRSZWYubmF0aXZlRWxlbWVudDtcclxuICAgICB0aGlzLl92aWV3cG9ydFNpemUgPSB2aWV3cG9ydEVsLmNsaWVudEhlaWdodDtcclxuICAgfVxyXG4gXHJcbiAgIC8qKiBRdWV1ZSB1cCBjaGFuZ2UgZGV0ZWN0aW9uIHRvIHJ1bi4gKi9cclxuICAgcHJpdmF0ZSBfbWFya0NoYW5nZURldGVjdGlvbk5lZWRlZChydW5BZnRlcj86IEZ1bmN0aW9uKSB7XHJcbiAgICAgaWYgKHJ1bkFmdGVyKSB7XHJcbiAgICAgICB0aGlzLl9ydW5BZnRlckNoYW5nZURldGVjdGlvbi5wdXNoKHJ1bkFmdGVyKTtcclxuICAgICB9XHJcbiBcclxuICAgICAvLyBVc2UgYSBQcm9taXNlIHRvIGJhdGNoIHRvZ2V0aGVyIGNhbGxzIHRvIGBfZG9DaGFuZ2VEZXRlY3Rpb25gLiBUaGlzIHdheSBpZiB3ZSBzZXQgYSBidW5jaCBvZlxyXG4gICAgIC8vIHByb3BlcnRpZXMgc2VxdWVudGlhbGx5IHdlIG9ubHkgaGF2ZSB0byBydW4gYF9kb0NoYW5nZURldGVjdGlvbmAgb25jZSBhdCB0aGUgZW5kLlxyXG4gICAgIGlmICghdGhpcy5faXNDaGFuZ2VEZXRlY3Rpb25QZW5kaW5nKSB7XHJcbiAgICAgICB0aGlzLl9pc0NoYW5nZURldGVjdGlvblBlbmRpbmcgPSB0cnVlO1xyXG4gICAgICAgdGhpcy5uZ1pvbmUucnVuT3V0c2lkZUFuZ3VsYXIoKCkgPT5cclxuICAgICAgICAgUHJvbWlzZS5yZXNvbHZlKCkudGhlbigoKSA9PiB7XHJcbiAgICAgICAgICAgdGhpcy5fZG9DaGFuZ2VEZXRlY3Rpb24oKTtcclxuICAgICAgICAgfSlcclxuICAgICAgICk7XHJcbiAgICAgfVxyXG4gICB9XHJcbiBcclxuICAgLyoqIFJ1biBjaGFuZ2UgZGV0ZWN0aW9uLiAqL1xyXG4gICBwcml2YXRlIF9kb0NoYW5nZURldGVjdGlvbigpIHtcclxuICAgICB0aGlzLl9pc0NoYW5nZURldGVjdGlvblBlbmRpbmcgPSBmYWxzZTtcclxuIFxyXG4gICAgIC8vIEFwcGx5IHRoZSBjb250ZW50IHRyYW5zZm9ybS4gVGhlIHRyYW5zZm9ybSBjYW4ndCBiZSBzZXQgdmlhIGFuIEFuZ3VsYXIgYmluZGluZyBiZWNhdXNlXHJcbiAgICAgLy8gYnlwYXNzU2VjdXJpdHlUcnVzdFN0eWxlIGlzIGJhbm5lZCBpbiBHb29nbGUuIEhvd2V2ZXIgdGhlIHZhbHVlIGlzIHNhZmUsIGl0J3MgY29tcG9zZWQgb2ZcclxuICAgICAvLyBzdHJpbmcgbGl0ZXJhbHMsIGEgdmFyaWFibGUgdGhhdCBjYW4gb25seSBiZSAnWCcgb3IgJ1knLCBhbmQgdXNlciBpbnB1dCB0aGF0IGlzIHJ1biB0aHJvdWdoXHJcbiAgICAgLy8gdGhlIGBOdW1iZXJgIGZ1bmN0aW9uIGZpcnN0IHRvIGNvZXJjZSBpdCB0byBhIG51bWVyaWMgdmFsdWUuXHJcbiAgICAgdGhpcy5fY29udGVudFdyYXBwZXIubmF0aXZlRWxlbWVudC5zdHlsZS50b3AgPSB0aGlzLl9yZW5kZXJlZENvbnRlbnRUcmFuc2Zvcm07XHJcbiAgICAgLy8gQXBwbHkgY2hhbmdlcyB0byBBbmd1bGFyIGJpbmRpbmdzLiBOb3RlOiBXZSBtdXN0IGNhbGwgYG1hcmtGb3JDaGVja2AgdG8gcnVuIGNoYW5nZSBkZXRlY3Rpb25cclxuICAgICAvLyBmcm9tIHRoZSByb290LCBzaW5jZSB0aGUgcmVwZWF0ZWQgaXRlbXMgYXJlIGNvbnRlbnQgcHJvamVjdGVkIGluLiBDYWxsaW5nIGBkZXRlY3RDaGFuZ2VzYFxyXG4gICAgIC8vIGluc3RlYWQgZG9lcyBub3QgcHJvcGVybHkgY2hlY2sgdGhlIHByb2plY3RlZCBjb250ZW50LlxyXG4gICAgIHRoaXMubmdab25lLnJ1bigoKSA9PiB0aGlzLl9jaGFuZ2VEZXRlY3RvclJlZi5tYXJrRm9yQ2hlY2soKSk7XHJcbiBcclxuICAgICBjb25zdCBydW5BZnRlckNoYW5nZURldGVjdGlvbiA9IHRoaXMuX3J1bkFmdGVyQ2hhbmdlRGV0ZWN0aW9uO1xyXG4gICAgIHRoaXMuX3J1bkFmdGVyQ2hhbmdlRGV0ZWN0aW9uID0gW107XHJcbiAgICAgZm9yIChjb25zdCBmbiBvZiBydW5BZnRlckNoYW5nZURldGVjdGlvbikge1xyXG4gICAgICAgZm4oKTtcclxuICAgICB9XHJcbiAgIH1cclxuIFxyXG4gICAvKiogQ2FsY3VsYXRlcyB0aGUgYHN0eWxlLndpZHRoYCBhbmQgYHN0eWxlLmhlaWdodGAgZm9yIHRoZSBzcGFjZXIgZWxlbWVudC4gKi9cclxuICAgcHJpdmF0ZSBfY2FsY3VsYXRlU3BhY2VyU2l6ZSgpIHtcclxuICAgICB0aGlzLl90b3RhbENvbnRlbnRIZWlnaHQgPSBgJHt0aGlzLl90b3RhbENvbnRlbnRTaXplfXB4YDtcclxuICAgICB0aGlzLl90b3RhbENvbnRlbnRXaWR0aCA9IFwiXCI7XHJcbiAgIH1cclxuIH1cclxuICIsIjwhLS1cclxuICBXcmFwIHRoZSByZW5kZXJlZCBjb250ZW50IGluIGFuIGVsZW1lbnQgdGhhdCB3aWxsIGJlIHVzZWQgdG8gb2Zmc2V0IGl0IGJhc2VkIG9uIHRoZSBzY3JvbGxcclxuICBwb3NpdGlvbi5cclxuLS0+XHJcbjxkaXYgI2NvbnRlbnRXcmFwcGVyIGNsYXNzPVwiYW5uYS10YWJsZS12aXJ0dWFsLXNjcm9sbC1jb250ZW50LXdyYXBwZXJcIj5cclxuXHQ8bmctY29udGVudD48L25nLWNvbnRlbnQ+XHJcbjwvZGl2PlxyXG48IS0tXHJcbiAgU3BhY2VyIHVzZWQgdG8gZm9yY2UgdGhlIHNjcm9sbGluZyBjb250YWluZXIgdG8gdGhlIGNvcnJlY3Qgc2l6ZSBmb3IgdGhlICp0b3RhbCogbnVtYmVyIG9mIGl0ZW1zXHJcbiAgc28gdGhhdCB0aGUgc2Nyb2xsYmFyIGNhcHR1cmVzIHRoZSBzaXplIG9mIHRoZSBlbnRpcmUgZGF0YSBzZXQuXHJcbi0tPlxyXG48ZGl2IGNsYXNzPVwiYXBwLXRhYmxlLXZpcnR1YWwtc2Nyb2xsLXNwYWNlclwiIFtzdHlsZS53aWR0aF09XCJfdG90YWxDb250ZW50V2lkdGhcIiBbc3R5bGUuaGVpZ2h0XT1cIl90b3RhbENvbnRlbnRIZWlnaHRcIj5cclxuPC9kaXY+Il19
|