@sumaris-net/ngx-components 18.23.19 → 18.23.20
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/doc/changelog.md +7 -0
- package/esm2022/src/app/core/account/account.page.mjs +63 -46
- package/esm2022/src/app/core/services/config/core.config.mjs +7 -1
- package/esm2022/src/app/core/services/model/config.model.mjs +6 -2
- package/esm2022/src/app/shared/image/image.service.mjs +2 -2
- package/esm2022/src/app/social/feed/feed.component.mjs +3 -3
- package/fesm2022/sumaris-net.ngx-components.mjs +75 -48
- package/fesm2022/sumaris-net.ngx-components.mjs.map +1 -1
- package/package.json +1 -1
- package/src/app/core/account/account.page.d.ts +4 -1
- package/src/app/core/services/config/core.config.d.ts +1 -0
- package/src/app/core/services/model/config.model.d.ts +1 -0
- package/src/app/shared/image/image.service.d.ts +1 -1
- package/src/assets/i18n/en-US.json +2 -1
- package/src/assets/i18n/en.json +2 -1
- package/src/assets/i18n/fr.json +2 -1
- package/src/assets/manifest.json +1 -1
|
@@ -92,6 +92,7 @@ export class AccountPage extends AppForm {
|
|
|
92
92
|
showTechnicalDetails = true;
|
|
93
93
|
showApiTokens = false;
|
|
94
94
|
showAvatar = false;
|
|
95
|
+
avatarMaxSize;
|
|
95
96
|
constructor(injector, formBuilder, accountService, network, navController, validatorService, configService, cd, imageService, environment, locales, appBaseHref) {
|
|
96
97
|
super(injector, validatorService.getFormGroup(accountService.account, { withSettings: true }));
|
|
97
98
|
this.formBuilder = formBuilder;
|
|
@@ -134,12 +135,17 @@ export class AccountPage extends AppForm {
|
|
|
134
135
|
setTimeout(() => this.tabGroup.realignInkBar(), 500);
|
|
135
136
|
}
|
|
136
137
|
async onChangeAvatar(event) {
|
|
137
|
-
if (!this.showAvatar || event.defaultPrevented)
|
|
138
|
+
if (!this.showAvatar || event.defaultPrevented || this.disabled)
|
|
138
139
|
return;
|
|
139
140
|
event.preventDefault();
|
|
140
141
|
event.stopPropagation();
|
|
141
142
|
try {
|
|
142
|
-
const images = await this.imageService.add(event, { multiple: false,
|
|
143
|
+
const images = await this.imageService.add(event, { multiple: false,
|
|
144
|
+
autoHideDropArea: true,
|
|
145
|
+
style: 'camera', // Force to use the camera (if Capacitor is enabled)
|
|
146
|
+
width: this.avatarMaxSize,
|
|
147
|
+
height: this.avatarMaxSize,
|
|
148
|
+
});
|
|
143
149
|
const img = firstArrayValue(images);
|
|
144
150
|
if (!img?.dataUrl)
|
|
145
151
|
return;
|
|
@@ -259,7 +265,7 @@ export class AccountPage extends AppForm {
|
|
|
259
265
|
}
|
|
260
266
|
async save(event) {
|
|
261
267
|
if (this.saving)
|
|
262
|
-
return false;
|
|
268
|
+
return false; // Already saving: skip
|
|
263
269
|
if (!this.form.valid) {
|
|
264
270
|
await AppFormUtils.waitWhilePending(this.form);
|
|
265
271
|
if (this.form.invalid) {
|
|
@@ -269,48 +275,52 @@ export class AccountPage extends AppForm {
|
|
|
269
275
|
}
|
|
270
276
|
}
|
|
271
277
|
this.submitted = true;
|
|
272
|
-
this.saving = true;
|
|
273
278
|
this.error = undefined;
|
|
274
|
-
|
|
275
|
-
...this.accountService.account.asObject(),
|
|
276
|
-
...this.form.value,
|
|
277
|
-
});
|
|
278
|
-
if (isNotEmptyArray(this.optionDefinitions) && this.propertiesTable) {
|
|
279
|
-
// Merge properties
|
|
280
|
-
await this.propertiesTable.save();
|
|
281
|
-
const propertyEntities = this.propertiesTable.value || [];
|
|
282
|
-
const properties = propertyEntities.reduce((res, item) => {
|
|
283
|
-
res[item.id] = item.value;
|
|
284
|
-
return res;
|
|
285
|
-
}, {});
|
|
286
|
-
const newProperties = { ...newAccount.settings.content['properties'], ...properties };
|
|
287
|
-
newAccount.settings.merge({ properties: newProperties }, ['properties']);
|
|
288
|
-
}
|
|
289
|
-
else if (newAccount.settings.content['properties']) {
|
|
290
|
-
// Clean properties
|
|
291
|
-
delete newAccount.settings.content['properties'];
|
|
292
|
-
}
|
|
293
|
-
if (this.tokensTable) {
|
|
294
|
-
await this.tokensTable.save();
|
|
295
|
-
newAccount.tokens = this.tokensTable.value;
|
|
296
|
-
}
|
|
297
|
-
console.debug('[account] Saving account...', newAccount);
|
|
279
|
+
this.markAsSaving();
|
|
298
280
|
try {
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
this.
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
281
|
+
const data = Account.fromObject({
|
|
282
|
+
...this.accountService.account.asObject(),
|
|
283
|
+
...this.form.value,
|
|
284
|
+
});
|
|
285
|
+
if (isNotEmptyArray(this.optionDefinitions) && this.propertiesTable) {
|
|
286
|
+
// Merge properties
|
|
287
|
+
await this.propertiesTable.save();
|
|
288
|
+
const propertyEntities = this.propertiesTable.value || [];
|
|
289
|
+
const properties = propertyEntities.reduce((res, item) => {
|
|
290
|
+
res[item.id] = item.value;
|
|
291
|
+
return res;
|
|
292
|
+
}, {});
|
|
293
|
+
const newProperties = { ...data.settings.content['properties'], ...properties };
|
|
294
|
+
data.settings.merge({ properties: newProperties }, ['properties']);
|
|
295
|
+
}
|
|
296
|
+
else if (data.settings.content['properties']) {
|
|
297
|
+
// Clean properties
|
|
298
|
+
delete data.settings.content['properties'];
|
|
299
|
+
}
|
|
300
|
+
if (this.tokensTable) {
|
|
301
|
+
await this.tokensTable.save();
|
|
302
|
+
data.tokens = this.tokensTable.value;
|
|
303
|
+
}
|
|
304
|
+
console.debug('[account] Saving account...', data);
|
|
305
|
+
try {
|
|
306
|
+
this.disable();
|
|
307
|
+
await this.accountService.save(data);
|
|
308
|
+
// Reload
|
|
309
|
+
setTimeout(() => this.onLogin(this.accountService.account), 100);
|
|
310
|
+
this.markAsPristine();
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
catch (err) {
|
|
314
|
+
console.error(err);
|
|
315
|
+
this.error = (err && err.message) || err;
|
|
316
|
+
return false;
|
|
317
|
+
}
|
|
318
|
+
finally {
|
|
319
|
+
this.enable();
|
|
320
|
+
}
|
|
310
321
|
}
|
|
311
322
|
finally {
|
|
312
|
-
this.
|
|
313
|
-
this.enable();
|
|
323
|
+
this.markAsSaved();
|
|
314
324
|
}
|
|
315
325
|
}
|
|
316
326
|
enable(opts) {
|
|
@@ -364,24 +374,31 @@ export class AccountPage extends AppForm {
|
|
|
364
374
|
// For compatibility with deprecated key
|
|
365
375
|
config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.DEFAULT_LAT_LONG_FORMAT_ENABLED);
|
|
366
376
|
this.showAvatar = config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.ACCOUNT_AVATAR_ENABLE);
|
|
377
|
+
this.avatarMaxSize = config.getPropertyAsInt(CORE_CONFIG_OPTIONS.ACCOUNT_AVATAR_MAX_SIZE);
|
|
367
378
|
const authTokenType = config.getProperty(CORE_CONFIG_OPTIONS.AUTH_TOKEN_TYPE);
|
|
368
379
|
this.canChangePassword = authTokenType === 'token';
|
|
369
380
|
this.showSecurityDetails = this.canChangePassword;
|
|
370
381
|
this.showApiTokens = config.getPropertyAsBoolean(CORE_CONFIG_OPTIONS.AUTH_API_TOKEN_ENABLED);
|
|
371
382
|
this.markForCheck();
|
|
372
383
|
}
|
|
384
|
+
openChangePasswordPage() {
|
|
385
|
+
return this.navController.navigateForward('account/password');
|
|
386
|
+
}
|
|
373
387
|
markForCheck() {
|
|
374
388
|
this.cd.markForCheck();
|
|
375
389
|
}
|
|
376
|
-
|
|
377
|
-
this.
|
|
390
|
+
markAsSaving() {
|
|
391
|
+
this.saving = true;
|
|
392
|
+
}
|
|
393
|
+
markAsSaved() {
|
|
394
|
+
this.saving = false;
|
|
378
395
|
}
|
|
379
396
|
static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AccountPage, deps: [{ token: i0.Injector }, { token: i1.UntypedFormBuilder }, { token: i2.AccountService }, { token: i3.NetworkService }, { token: i4.NavController }, { token: i5.AccountValidatorService }, { token: i6.ConfigService }, { token: i0.ChangeDetectorRef }, { token: i7.ImageService }, { token: ENVIRONMENT }, { token: APP_LOCALES }, { token: APP_BASE_HREF, optional: true }], target: i0.ɵɵFactoryTarget.Component });
|
|
380
|
-
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AccountPage, selector: "app-account-page", host: { listeners: { "window:beforeunload": "handleRefresh($event)" } }, viewQueries: [{ propertyName: "tabGroup", first: true, predicate: ["tabGroup"], descendants: true, static: true }, { propertyName: "propertiesTable", first: true, predicate: ["propertiesTable"], descendants: true, static: true }, { propertyName: "tokensTable", first: true, predicate: ["tokensTable"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'ACCOUNT.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save()\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n @if (loading || saving) {\n <!-- loader -->\n <ion-spinner></ion-spinner>\n } @else if (network.online) {\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n <!-- error -->\n @if (mobile && (errorSubject | async); as error) {\n <ion-item lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n }\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n <mat-tab-group\n #tabGroup\n [(selectedIndex)]=\"selectedTabIndex\"\n class=\"mat-mdc-tab-disabled-hidden\"\n [mat-stretch-tabs]=\"mobile\"\n dynamicHeight\n >\n <!-- TAB: user details -->\n <mat-tab [label]=\"'ACCOUNT.USER_DETAILS.TITLE' | translate\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{ 'ACCOUNT.USER_DETAILS.TITLE' | translate }}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- Avatar block -->\n @if (showAvatar) {\n @let accountAvatar = form?.controls?.avatar?.value || form?.value?.avatar || accountService?.account?.avatar || defaultAvatarImage;\n @let isDefaultAvatar = accountAvatar?.endsWith(defaultAvatarImage);\n <ion-item lines=\"none\" class=\"ion-margin-bottom\" style=\"--inner-padding-end: 0\">\n <ion-button slot=\"start\" fill=\"clear\"\n class=\"user-avatar\"\n [style.background-image]=\"'url(' + (accountAvatar || defaultAvatarImage) + ')'\"\n (click)=\"onChangeAvatar($event)\"\n [matTooltip]=\"'IMAGE.BTN_CAMERA_SOURCE' | translate\"\n >\n @if (!accountReadOnly) {\n <ion-icon [class.visible-hover]=\"!isDefaultAvatar\" name=\"camera\" slot=\"icon-only\"></ion-icon>\n }\n </ion-button>\n </ion-item>\n }\n\n <ion-list-header><p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION' | translate\"></p></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Email -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input matInput formControlName=\"email\" autocomplete=\"section-red email\" />\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n @if (email?.notConfirmed) {\n <ion-item lines=\"none\">\n <ion-grid class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL' | translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px\">\n <ion-col style=\"text-align: right\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION' | translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n @if (!email.sending) {\n <ion-button fill=\"solid\" color=\"secondary\" (click)=\"sendConfirmationEmail($event)\">\n {{ 'ACCOUNT.BTN_RESEND' | translate }}\n </ion-button>\n } @else {\n <ion-spinner class=\"ion-no-padding\"></ion-spinner>\n }\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error | translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n }\n <!-- Last name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required\n />\n <mat-error\n *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- First name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Additional fields -->\n @for (definition of additionalFields; track definition.key) {\n <ion-item lines=\"none\">\n <app-form-field\n [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"\n (definition.extra && definition.extra.account && definition.extra.account.required) || false\n \"\n ></app-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Security -->\n @if (showSecurityDetails) {\n <ion-list-header><h3 translate>ACCOUNT.SECURITY.TITLE</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item\n [button]=\"mobile\"\n routerDirection=\"forward\"\n lines=\"none\"\n (click)=\"openChangePasswordPage()\"\n [disabled]=\"disabled\"\n >\n @if (!mobile) {\n <ion-icon slot=\"start\" name=\"keypad\"></ion-icon>\n <ion-label>{{ 'ACCOUNT.SECURITY.PASSWORD' | translate }}</ion-label>\n }\n <ion-text color=\"tertiary\">{{ 'ACCOUNT.SECURITY.BTN_CHANGE_PASSWORD' | translate }}</ion-text>\n @if (!mobile) {\n <ion-icon slot=\"end\" color=\"tertiary\" name=\"chevron-forward\"></ion-icon>\n }\n </ion-item>\n </ion-list>\n }\n\n <!-- Technical details -->\n @if (showTechnicalDetails) {\n <ion-list-header><h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- profile -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PROFILE' | translate }}</mat-label>\n <input matInput hidden readonly=\"true\" formControlName=\"mainProfile\" required />\n <span>{{ 'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate }}</span>\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- pubkey -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PUBKEY' | translate }}</mat-label>\n <input matInput readonly=\"true\" formControlName=\"pubkey\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab [label]=\"'ACCOUNT.SETTINGS.TITLE' | translate\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION' | translate\"></p>\n\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n </mat-select>\n <mat-error\n *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n @if (showLatLonFormat) {\n @let control = settingsForm | formGetControl: 'latLongFormat';\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select [formControl]=\"control\" required>\n @for (item of latLongFormats; track item) {\n <mat-option [value]=\"item\">\n {{ 'COMMON.LAT_LONG.ENUM.' + item | uppercase | translate }}\n </mat-option>\n }\n </mat-select>\n @if (control.dirty && control.hasError('required')) {\n <mat-error translate>ERROR.FIELD_REQUIRED</mat-error>\n }\n </mat-form-field>\n }\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\" [class.cdk-visually-hidden]=\"optionDefinitions | isEmptyArray\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n </mat-tab>\n\n <!-- TAB: tokens -->\n <mat-tab [label]=\"'ACCOUNT.TOKENS.TITLE' | translate\" formGroupName=\"tokens\" [disabled]=\"!showApiTokens\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"ticket\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.TOKENS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.TOKENS.DESCRIPTION' | translate\"></p>\n </div>\n <!-- Tokens table -->\n <div class=\"tokens-table\">\n <app-user-token-table\n #tokensTable\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-user-token-table>\n </div>\n </mat-tab>\n </mat-tab-group>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save()\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}.user-avatar{-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;background-repeat:no-repeat;background-position:center;background-color:var(--ion-color-secondary);overflow:hidden!important;font-size:var(--avatar-size, 96px)!important;line-height:var(--avatar-size, 96px);height:var(--avatar-size, 96px)!important;width:var(--avatar-size, 96px)!important;border:solid 1px rgba(var(--ion-color-secondary-rgb),.5);border-radius:50%;display:inline-block}.user-avatar ion-icon{position:fixed;left:0;bottom:16px;width:var(--avatar-size, 96px)}.user-avatar .visible-hover{display:none;visibility:hidden}.user-avatar:hover{background-color:rgba(var(--ion-color-secondary-rgb),.8);border:solid 2px var(--ion-color-secondary-shade);cursor:pointer}.user-avatar:hover .visible-hover{display:inline;visibility:visible}div.options-table{height:calc(100vh - 380px)}div.tokens-table{height:calc(100vh - 250px)}\n"], dependencies: [{ kind: "directive", type: i8.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i4.IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: i4.IonRow, selector: "ion-row" }, { kind: "component", type: i4.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i4.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i13.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i14.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i15.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i15.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i15.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "directive", type: i16.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i17.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: i18.ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "id", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: i19.AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug", "panelClass", "panelWidth"], outputs: ["keyup.enter"] }, { kind: "component", type: i20.FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i21.AppPropertiesTable, selector: "app-properties-table", inputs: ["definitions", "showToolbar"] }, { kind: "component", type: i22.AppInstallUpgradeCard, selector: "app-install-upgrade-card", inputs: ["isLogin", "showUpgradeWarning", "showOfflineWarning", "showInstallButton", "debug"] }, { kind: "component", type: i23.UserTokenTable, selector: "app-user-token-table", inputs: ["useSticky"] }, { kind: "pipe", type: i8.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "pipe", type: i24.EmptyArrayPipe, name: "isEmptyArray" }, { kind: "pipe", type: i25.FormGetControlPipe, name: "formGetControl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
397
|
+
static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.13", type: AccountPage, selector: "app-account-page", host: { listeners: { "window:beforeunload": "handleRefresh($event)" } }, viewQueries: [{ propertyName: "tabGroup", first: true, predicate: ["tabGroup"], descendants: true, static: true }, { propertyName: "propertiesTable", first: true, predicate: ["propertiesTable"], descendants: true, static: true }, { propertyName: "tokensTable", first: true, predicate: ["tokensTable"], descendants: true, static: true }], usesInheritance: true, ngImport: i0, template: "<app-toolbar\n [title]=\"'ACCOUNT.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save()\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n @if (loading || saving) {\n <!-- loader -->\n <ion-spinner></ion-spinner>\n } @else if (network.online) {\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n <!-- error -->\n @if (mobile && (errorSubject | async); as error) {\n <ion-item lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n }\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n <mat-tab-group\n #tabGroup\n [(selectedIndex)]=\"selectedTabIndex\"\n class=\"mat-mdc-tab-disabled-hidden\"\n [mat-stretch-tabs]=\"mobile\"\n dynamicHeight\n >\n <!-- TAB: user details -->\n <mat-tab [label]=\"'ACCOUNT.USER_DETAILS.TITLE' | translate\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{ 'ACCOUNT.USER_DETAILS.TITLE' | translate }}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- Avatar block -->\n @if (showAvatar) {\n @let accountAvatar = form?.controls?.avatar?.value || form?.value?.avatar || accountService?.account?.avatar || defaultAvatarImage;\n @let isDefaultAvatar = accountAvatar?.endsWith(defaultAvatarImage);\n <ion-item lines=\"none\" class=\"ion-margin-bottom\" style=\"--inner-padding-end: 0\">\n <ion-button slot=\"start\" fill=\"clear\"\n class=\"user-avatar\"\n [style.background-image]=\"'url(' + (accountAvatar || defaultAvatarImage) + ')'\"\n (click)=\"onChangeAvatar($event)\"\n [disabled]=\"disabled\"\n [matTooltip]=\"'IMAGE.BTN_CAMERA_SOURCE' | translate\"\n >\n @if (!accountReadOnly && enabled) {\n <ion-icon [class.visible-hover]=\"!isDefaultAvatar\" name=\"camera\" slot=\"icon-only\"></ion-icon>\n }\n </ion-button>\n </ion-item>\n }\n\n <ion-list-header><p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION' | translate\"></p></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Email -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input matInput formControlName=\"email\" autocomplete=\"section-red email\" />\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n @if (email?.notConfirmed) {\n <ion-item lines=\"none\">\n <ion-grid class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL' | translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px\">\n <ion-col style=\"text-align: right\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION' | translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n @if (!email.sending) {\n <ion-button fill=\"solid\" color=\"secondary\" (click)=\"sendConfirmationEmail($event)\">\n {{ 'ACCOUNT.BTN_RESEND' | translate }}\n </ion-button>\n } @else {\n <ion-spinner class=\"ion-no-padding\"></ion-spinner>\n }\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error | translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n }\n <!-- Last name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required\n />\n <mat-error\n *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- First name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Additional fields -->\n @for (definition of additionalFields; track definition.key) {\n <ion-item lines=\"none\">\n <app-form-field\n [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"\n (definition.extra && definition.extra.account && definition.extra.account.required) || false\n \"\n ></app-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Security -->\n @if (showSecurityDetails) {\n <ion-list-header><h3 translate>ACCOUNT.SECURITY.TITLE</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item\n [button]=\"mobile\"\n routerDirection=\"forward\"\n lines=\"none\"\n (click)=\"openChangePasswordPage()\"\n [disabled]=\"disabled\"\n >\n @if (!mobile) {\n <ion-icon slot=\"start\" name=\"keypad\"></ion-icon>\n <ion-label>{{ 'ACCOUNT.SECURITY.PASSWORD' | translate }}</ion-label>\n }\n <ion-text color=\"tertiary\">{{ 'ACCOUNT.SECURITY.BTN_CHANGE_PASSWORD' | translate }}</ion-text>\n @if (!mobile) {\n <ion-icon slot=\"end\" color=\"tertiary\" name=\"chevron-forward\"></ion-icon>\n }\n </ion-item>\n </ion-list>\n }\n\n <!-- Technical details -->\n @if (showTechnicalDetails) {\n <ion-list-header><h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- profile -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PROFILE' | translate }}</mat-label>\n <input matInput hidden readonly=\"true\" formControlName=\"mainProfile\" required />\n <span>{{ 'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate }}</span>\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- pubkey -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PUBKEY' | translate }}</mat-label>\n <input matInput readonly=\"true\" formControlName=\"pubkey\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab [label]=\"'ACCOUNT.SETTINGS.TITLE' | translate\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION' | translate\"></p>\n\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n </mat-select>\n <mat-error\n *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n @if (showLatLonFormat) {\n @let control = settingsForm | formGetControl: 'latLongFormat';\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select [formControl]=\"control\" required>\n @for (item of latLongFormats; track item) {\n <mat-option [value]=\"item\">\n {{ 'COMMON.LAT_LONG.ENUM.' + item | uppercase | translate }}\n </mat-option>\n }\n </mat-select>\n @if (control.dirty && control.hasError('required')) {\n <mat-error translate>ERROR.FIELD_REQUIRED</mat-error>\n }\n </mat-form-field>\n }\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\" [class.cdk-visually-hidden]=\"optionDefinitions | isEmptyArray\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n </mat-tab>\n\n <!-- TAB: tokens -->\n <mat-tab [label]=\"'ACCOUNT.TOKENS.TITLE' | translate\" formGroupName=\"tokens\" [disabled]=\"!showApiTokens\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"ticket\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.TOKENS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.TOKENS.DESCRIPTION' | translate\"></p>\n </div>\n <!-- Tokens table -->\n <div class=\"tokens-table\">\n <app-user-token-table\n #tokensTable\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-user-token-table>\n </div>\n </mat-tab>\n </mat-tab-group>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save()\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}.user-avatar{-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;background-repeat:no-repeat;background-position:center;background-color:var(--ion-color-secondary);overflow:hidden!important;font-size:var(--avatar-size, 96px)!important;line-height:var(--avatar-size, 96px);height:var(--avatar-size, 96px)!important;width:var(--avatar-size, 96px)!important;border:solid 1px rgba(var(--ion-color-secondary-rgb),.5);border-radius:50%;display:inline-block}.user-avatar ion-icon{position:fixed;left:0;bottom:16px;width:var(--avatar-size, 96px)}.user-avatar .visible-hover{display:none;visibility:hidden}.user-avatar:hover{background-color:rgba(var(--ion-color-secondary-rgb),.8);border:solid 2px var(--ion-color-secondary-shade);cursor:pointer}.user-avatar:hover .visible-hover{display:inline;visibility:visible}div.options-table{height:calc(100vh - 380px)}div.tokens-table{height:calc(100vh - 250px)}\n"], dependencies: [{ kind: "directive", type: i8.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i8.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "component", type: i4.IonButton, selector: "ion-button", inputs: ["buttonType", "color", "disabled", "download", "expand", "fill", "form", "href", "mode", "rel", "routerAnimation", "routerDirection", "shape", "size", "strong", "target", "type"] }, { kind: "component", type: i4.IonButtons, selector: "ion-buttons", inputs: ["collapse"] }, { kind: "component", type: i4.IonCol, selector: "ion-col", inputs: ["offset", "offsetLg", "offsetMd", "offsetSm", "offsetXl", "offsetXs", "pull", "pullLg", "pullMd", "pullSm", "pullXl", "pullXs", "push", "pushLg", "pushMd", "pushSm", "pushXl", "pushXs", "size", "sizeLg", "sizeMd", "sizeSm", "sizeXl", "sizeXs"] }, { kind: "component", type: i4.IonContent, selector: "ion-content", inputs: ["color", "forceOverscroll", "fullscreen", "scrollEvents", "scrollX", "scrollY"] }, { kind: "component", type: i4.IonFooter, selector: "ion-footer", inputs: ["collapse", "mode", "translucent"] }, { kind: "component", type: i4.IonGrid, selector: "ion-grid", inputs: ["fixed"] }, { kind: "component", type: i4.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: i4.IonItem, selector: "ion-item", inputs: ["button", "color", "counter", "counterFormatter", "detail", "detailIcon", "disabled", "download", "fill", "href", "lines", "mode", "rel", "routerAnimation", "routerDirection", "shape", "target", "type"] }, { kind: "component", type: i4.IonLabel, selector: "ion-label", inputs: ["color", "mode", "position"] }, { kind: "component", type: i4.IonList, selector: "ion-list", inputs: ["inset", "lines", "mode"] }, { kind: "component", type: i4.IonListHeader, selector: "ion-list-header", inputs: ["color", "lines", "mode"] }, { kind: "component", type: i4.IonRow, selector: "ion-row" }, { kind: "component", type: i4.IonSpinner, selector: "ion-spinner", inputs: ["color", "duration", "name", "paused"] }, { kind: "component", type: i4.IonText, selector: "ion-text", inputs: ["color", "mode"] }, { kind: "directive", type: i9.TranslateDirective, selector: "[translate],[ngx-translate]", inputs: ["translate", "translateParams"] }, { kind: "directive", type: i1.ɵNgNoValidate, selector: "form:not([ngNoForm]):not([ngNativeValidate])" }, { kind: "directive", type: i1.DefaultValueAccessor, selector: "input:not([type=checkbox])[formControlName],textarea[formControlName],input:not([type=checkbox])[formControl],textarea[formControl],input:not([type=checkbox])[ngModel],textarea[ngModel],[ngDefaultControl]" }, { kind: "directive", type: i1.NgControlStatus, selector: "[formControlName],[ngModel],[formControl]" }, { kind: "directive", type: i1.NgControlStatusGroup, selector: "[formGroupName],[formArrayName],[ngModelGroup],[formGroup],form:not([ngNoForm]),[ngForm]" }, { kind: "directive", type: i1.RequiredValidator, selector: ":not([type=checkbox])[required][formControlName],:not([type=checkbox])[required][formControl],:not([type=checkbox])[required][ngModel]", inputs: ["required"] }, { kind: "directive", type: i1.FormControlDirective, selector: "[formControl]", inputs: ["formControl", "disabled", "ngModel"], outputs: ["ngModelChange"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormGroupDirective, selector: "[formGroup]", inputs: ["formGroup"], outputs: ["ngSubmit"], exportAs: ["ngForm"] }, { kind: "directive", type: i1.FormControlName, selector: "[formControlName]", inputs: ["formControlName", "disabled", "ngModel"], outputs: ["ngModelChange"] }, { kind: "directive", type: i1.FormGroupName, selector: "[formGroupName]", inputs: ["formGroupName"] }, { kind: "component", type: i10.MatFormField, selector: "mat-form-field", inputs: ["hideRequiredMarker", "color", "floatLabel", "appearance", "subscriptSizing", "hintLabel"], exportAs: ["matFormField"] }, { kind: "directive", type: i10.MatLabel, selector: "mat-label" }, { kind: "directive", type: i10.MatError, selector: "mat-error, [matError]", inputs: ["id"] }, { kind: "directive", type: i10.MatPrefix, selector: "[matPrefix], [matIconPrefix], [matTextPrefix]", inputs: ["matTextPrefix"] }, { kind: "directive", type: i11.MatInput, selector: "input[matInput], textarea[matInput], select[matNativeControl], input[matNativeControl], textarea[matNativeControl]", inputs: ["disabled", "id", "placeholder", "name", "required", "type", "errorStateMatcher", "aria-describedby", "value", "readonly"], exportAs: ["matInput"] }, { kind: "component", type: i12.MatIcon, selector: "mat-icon", inputs: ["color", "inline", "svgIcon", "fontSet", "fontIcon"], exportAs: ["matIcon"] }, { kind: "component", type: i13.MatSelect, selector: "mat-select", inputs: ["aria-describedby", "panelClass", "disabled", "disableRipple", "tabIndex", "hideSingleSelectionIndicator", "placeholder", "required", "multiple", "disableOptionCentering", "compareWith", "value", "aria-label", "aria-labelledby", "errorStateMatcher", "typeaheadDebounceInterval", "sortComparator", "id", "panelWidth"], outputs: ["openedChange", "opened", "closed", "selectionChange", "valueChange"], exportAs: ["matSelect"] }, { kind: "component", type: i14.MatOption, selector: "mat-option", inputs: ["value", "id", "disabled"], outputs: ["onSelectionChange"], exportAs: ["matOption"] }, { kind: "directive", type: i15.MatTabLabel, selector: "[mat-tab-label], [matTabLabel]" }, { kind: "component", type: i15.MatTab, selector: "mat-tab", inputs: ["disabled", "label", "aria-label", "aria-labelledby", "labelClass", "bodyClass"], exportAs: ["matTab"] }, { kind: "component", type: i15.MatTabGroup, selector: "mat-tab-group", inputs: ["color", "fitInkBarToContent", "mat-stretch-tabs", "dynamicHeight", "selectedIndex", "headerPosition", "animationDuration", "contentTabIndex", "disablePagination", "disableRipple", "preserveContent", "backgroundColor", "aria-label", "aria-labelledby"], outputs: ["selectedIndexChange", "focusChange", "animationDone", "selectedTabChange"], exportAs: ["matTabGroup"] }, { kind: "directive", type: i16.MatTooltip, selector: "[matTooltip]", inputs: ["matTooltipPosition", "matTooltipPositionAtOrigin", "matTooltipDisabled", "matTooltipShowDelay", "matTooltipHideDelay", "matTooltipTouchGestures", "matTooltip", "matTooltipClass"], exportAs: ["matTooltip"] }, { kind: "directive", type: i17.AutofocusDirective, selector: "[autofocus], input[appAutofocus]", inputs: ["appAutofocus", "autofocusDelay"] }, { kind: "component", type: i18.ToolbarComponent, selector: "app-toolbar", inputs: ["progressBarMode", "title", "color", "class", "id", "backHref", "defaultBackHref", "hasValidate", "hasClose", "hasSearch", "canGoBack", "canShowMenu"], outputs: ["onValidate", "onClose", "onValidateAndClose", "onBackClick", "onSearch"] }, { kind: "component", type: i19.AppFormField, selector: "app-form-field", inputs: ["definition", "readonly", "disabled", "formControl", "formControlName", "placeholder", "compact", "required", "hideRequiredMarker", "floatLabel", "label", "appearance", "subscriptSizing", "tabindex", "autofocus", "clearable", "chipColor", "class", "debug", "panelClass", "panelWidth"], outputs: ["keyup.enter"] }, { kind: "component", type: i20.FormButtonsBarComponent, selector: "app-form-buttons-bar", inputs: ["disabled", "disabledCancel", "disabledEscape", "classList", "saveButtonColor", "backText", "cancelText", "nextText", "showBack", "showCancel", "showNext", "showSave"], outputs: ["onCancel", "onSave", "onNext", "onBack", "onSaveAndClose", "onSaveAndNext"] }, { kind: "component", type: i21.AppPropertiesTable, selector: "app-properties-table", inputs: ["definitions", "showToolbar"] }, { kind: "component", type: i22.AppInstallUpgradeCard, selector: "app-install-upgrade-card", inputs: ["isLogin", "showUpgradeWarning", "showOfflineWarning", "showInstallButton", "debug"] }, { kind: "component", type: i23.UserTokenTable, selector: "app-user-token-table", inputs: ["useSticky"] }, { kind: "pipe", type: i8.AsyncPipe, name: "async" }, { kind: "pipe", type: i8.UpperCasePipe, name: "uppercase" }, { kind: "pipe", type: i9.TranslatePipe, name: "translate" }, { kind: "pipe", type: i24.EmptyArrayPipe, name: "isEmptyArray" }, { kind: "pipe", type: i25.FormGetControlPipe, name: "formGetControl" }], changeDetection: i0.ChangeDetectionStrategy.OnPush });
|
|
381
398
|
}
|
|
382
399
|
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImport: i0, type: AccountPage, decorators: [{
|
|
383
400
|
type: Component,
|
|
384
|
-
args: [{ selector: 'app-account-page', changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'ACCOUNT.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save()\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n @if (loading || saving) {\n <!-- loader -->\n <ion-spinner></ion-spinner>\n } @else if (network.online) {\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n <!-- error -->\n @if (mobile && (errorSubject | async); as error) {\n <ion-item lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n }\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n <mat-tab-group\n #tabGroup\n [(selectedIndex)]=\"selectedTabIndex\"\n class=\"mat-mdc-tab-disabled-hidden\"\n [mat-stretch-tabs]=\"mobile\"\n dynamicHeight\n >\n <!-- TAB: user details -->\n <mat-tab [label]=\"'ACCOUNT.USER_DETAILS.TITLE' | translate\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{ 'ACCOUNT.USER_DETAILS.TITLE' | translate }}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- Avatar block -->\n @if (showAvatar) {\n @let accountAvatar = form?.controls?.avatar?.value || form?.value?.avatar || accountService?.account?.avatar || defaultAvatarImage;\n @let isDefaultAvatar = accountAvatar?.endsWith(defaultAvatarImage);\n <ion-item lines=\"none\" class=\"ion-margin-bottom\" style=\"--inner-padding-end: 0\">\n <ion-button slot=\"start\" fill=\"clear\"\n class=\"user-avatar\"\n [style.background-image]=\"'url(' + (accountAvatar || defaultAvatarImage) + ')'\"\n (click)=\"onChangeAvatar($event)\"\n [matTooltip]=\"'IMAGE.BTN_CAMERA_SOURCE' | translate\"\n >\n @if (!accountReadOnly) {\n <ion-icon [class.visible-hover]=\"!isDefaultAvatar\" name=\"camera\" slot=\"icon-only\"></ion-icon>\n }\n </ion-button>\n </ion-item>\n }\n\n <ion-list-header><p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION' | translate\"></p></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Email -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input matInput formControlName=\"email\" autocomplete=\"section-red email\" />\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n @if (email?.notConfirmed) {\n <ion-item lines=\"none\">\n <ion-grid class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL' | translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px\">\n <ion-col style=\"text-align: right\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION' | translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n @if (!email.sending) {\n <ion-button fill=\"solid\" color=\"secondary\" (click)=\"sendConfirmationEmail($event)\">\n {{ 'ACCOUNT.BTN_RESEND' | translate }}\n </ion-button>\n } @else {\n <ion-spinner class=\"ion-no-padding\"></ion-spinner>\n }\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error | translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n }\n <!-- Last name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required\n />\n <mat-error\n *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- First name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Additional fields -->\n @for (definition of additionalFields; track definition.key) {\n <ion-item lines=\"none\">\n <app-form-field\n [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"\n (definition.extra && definition.extra.account && definition.extra.account.required) || false\n \"\n ></app-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Security -->\n @if (showSecurityDetails) {\n <ion-list-header><h3 translate>ACCOUNT.SECURITY.TITLE</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item\n [button]=\"mobile\"\n routerDirection=\"forward\"\n lines=\"none\"\n (click)=\"openChangePasswordPage()\"\n [disabled]=\"disabled\"\n >\n @if (!mobile) {\n <ion-icon slot=\"start\" name=\"keypad\"></ion-icon>\n <ion-label>{{ 'ACCOUNT.SECURITY.PASSWORD' | translate }}</ion-label>\n }\n <ion-text color=\"tertiary\">{{ 'ACCOUNT.SECURITY.BTN_CHANGE_PASSWORD' | translate }}</ion-text>\n @if (!mobile) {\n <ion-icon slot=\"end\" color=\"tertiary\" name=\"chevron-forward\"></ion-icon>\n }\n </ion-item>\n </ion-list>\n }\n\n <!-- Technical details -->\n @if (showTechnicalDetails) {\n <ion-list-header><h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- profile -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PROFILE' | translate }}</mat-label>\n <input matInput hidden readonly=\"true\" formControlName=\"mainProfile\" required />\n <span>{{ 'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate }}</span>\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- pubkey -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PUBKEY' | translate }}</mat-label>\n <input matInput readonly=\"true\" formControlName=\"pubkey\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab [label]=\"'ACCOUNT.SETTINGS.TITLE' | translate\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION' | translate\"></p>\n\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n </mat-select>\n <mat-error\n *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n @if (showLatLonFormat) {\n @let control = settingsForm | formGetControl: 'latLongFormat';\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select [formControl]=\"control\" required>\n @for (item of latLongFormats; track item) {\n <mat-option [value]=\"item\">\n {{ 'COMMON.LAT_LONG.ENUM.' + item | uppercase | translate }}\n </mat-option>\n }\n </mat-select>\n @if (control.dirty && control.hasError('required')) {\n <mat-error translate>ERROR.FIELD_REQUIRED</mat-error>\n }\n </mat-form-field>\n }\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\" [class.cdk-visually-hidden]=\"optionDefinitions | isEmptyArray\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n </mat-tab>\n\n <!-- TAB: tokens -->\n <mat-tab [label]=\"'ACCOUNT.TOKENS.TITLE' | translate\" formGroupName=\"tokens\" [disabled]=\"!showApiTokens\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"ticket\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.TOKENS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.TOKENS.DESCRIPTION' | translate\"></p>\n </div>\n <!-- Tokens table -->\n <div class=\"tokens-table\">\n <app-user-token-table\n #tokensTable\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-user-token-table>\n </div>\n </mat-tab>\n </mat-tab-group>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save()\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}.user-avatar{-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;background-repeat:no-repeat;background-position:center;background-color:var(--ion-color-secondary);overflow:hidden!important;font-size:var(--avatar-size, 96px)!important;line-height:var(--avatar-size, 96px);height:var(--avatar-size, 96px)!important;width:var(--avatar-size, 96px)!important;border:solid 1px rgba(var(--ion-color-secondary-rgb),.5);border-radius:50%;display:inline-block}.user-avatar ion-icon{position:fixed;left:0;bottom:16px;width:var(--avatar-size, 96px)}.user-avatar .visible-hover{display:none;visibility:hidden}.user-avatar:hover{background-color:rgba(var(--ion-color-secondary-rgb),.8);border:solid 2px var(--ion-color-secondary-shade);cursor:pointer}.user-avatar:hover .visible-hover{display:inline;visibility:visible}div.options-table{height:calc(100vh - 380px)}div.tokens-table{height:calc(100vh - 250px)}\n"] }]
|
|
401
|
+
args: [{ selector: 'app-account-page', changeDetection: ChangeDetectionStrategy.OnPush, template: "<app-toolbar\n [title]=\"'ACCOUNT.TITLE' | translate\"\n color=\"primary\"\n [hasValidate]=\"dirty && !saving\"\n [hasClose]=\"!dirty && !saving\"\n (onValidate)=\"save()\"\n (onClose)=\"close($event)\"\n>\n <ion-buttons slot=\"end\">\n @if (loading || saving) {\n <!-- loader -->\n <ion-spinner></ion-spinner>\n } @else if (network.online) {\n <!-- refresh button (if online) -->\n <ion-button [matTooltip]=\"'COMMON.BTN_REFRESH' | translate\" (click)=\"refresh($event)\">\n <mat-icon slot=\"icon-only\">refresh</mat-icon>\n </ion-button>\n }\n </ion-buttons>\n</app-toolbar>\n\n<ion-content>\n <!-- Install (and upgrade) card -->\n <app-install-upgrade-card [isLogin]=\"isLogin\" [showInstallButton]=\"true\"></app-install-upgrade-card>\n\n <!-- error -->\n @if (mobile && (errorSubject | async); as error) {\n <ion-item lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n }\n\n <form [formGroup]=\"form\" novalidate class=\"form-container\">\n <mat-tab-group\n #tabGroup\n [(selectedIndex)]=\"selectedTabIndex\"\n class=\"mat-mdc-tab-disabled-hidden\"\n [mat-stretch-tabs]=\"mobile\"\n dynamicHeight\n >\n <!-- TAB: user details -->\n <mat-tab [label]=\"'ACCOUNT.USER_DETAILS.TITLE' | translate\" class=\"ion-padding\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"person-circle\"></ion-icon>\n </mat-icon>\n <ion-label>{{ 'ACCOUNT.USER_DETAILS.TITLE' | translate }}</ion-label>\n <ion-icon slot=\"end\" name=\"alert-circle\" color=\"danger\" *ngIf=\"submitted && form.invalid\"></ion-icon>\n </ng-template>\n <ion-grid class=\"ion-no-padding\">\n <ion-row>\n <!-- left margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n\n <ion-col class=\"ion-padding\">\n <!-- Avatar block -->\n @if (showAvatar) {\n @let accountAvatar = form?.controls?.avatar?.value || form?.value?.avatar || accountService?.account?.avatar || defaultAvatarImage;\n @let isDefaultAvatar = accountAvatar?.endsWith(defaultAvatarImage);\n <ion-item lines=\"none\" class=\"ion-margin-bottom\" style=\"--inner-padding-end: 0\">\n <ion-button slot=\"start\" fill=\"clear\"\n class=\"user-avatar\"\n [style.background-image]=\"'url(' + (accountAvatar || defaultAvatarImage) + ')'\"\n (click)=\"onChangeAvatar($event)\"\n [disabled]=\"disabled\"\n [matTooltip]=\"'IMAGE.BTN_CAMERA_SOURCE' | translate\"\n >\n @if (!accountReadOnly && enabled) {\n <ion-icon [class.visible-hover]=\"!isDefaultAvatar\" name=\"camera\" slot=\"icon-only\"></ion-icon>\n }\n </ion-button>\n </ion-item>\n }\n\n <ion-list-header><p [innerHTML]=\"'ACCOUNT.USER_DETAILS.DESCRIPTION' | translate\"></p></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- Email -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.EMAIL' | translate }}</mat-label>\n <input matInput formControlName=\"email\" autocomplete=\"section-red email\" />\n <mat-error *ngIf=\"form.controls.email.hasError('required') && form.controls.email.dirty\" translate>\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.email.hasError('email') && form.controls.email.dirty\">\n <span>{{ 'ERROR.FIELD_NOT_VALID_EMAIL' | translate }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n @if (email?.notConfirmed) {\n <ion-item lines=\"none\">\n <ion-grid class=\"ion-no-padding ion-padding-bottom\">\n <ion-row>\n <ion-col color=\"danger\">\n <ion-icon slot=\"start\" color=\"danger\" name=\"alert-circle\"></ion-icon>\n <ion-text [innerHTML]=\"'ACCOUNT.EMAIL_NOT_CONFIRMED_LABEL' | translate\"></ion-text>\n </ion-col>\n </ion-row>\n\n <ion-row style=\"height: 51px\">\n <ion-col style=\"text-align: right\">\n <ion-text>\n <small [innerHTML]=\"'ACCOUNT.EMAIL_NOT_RECEIVED_QUESTION' | translate\"></small>\n </ion-text>\n </ion-col>\n <ion-col size=\"auto\">\n @if (!email.sending) {\n <ion-button fill=\"solid\" color=\"secondary\" (click)=\"sendConfirmationEmail($event)\">\n {{ 'ACCOUNT.BTN_RESEND' | translate }}\n </ion-button>\n } @else {\n <ion-spinner class=\"ion-no-padding\"></ion-spinner>\n }\n </ion-col>\n </ion-row>\n\n <ion-row *ngIf=\"email.error && !email.sending\">\n <ion-col>\n <span *ngIf=\"email.error && !email.sending\" [innerHTML]=\"email.error | translate\"></span>\n </ion-col>\n </ion-row>\n </ion-grid>\n </ion-item>\n }\n <!-- Last name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.LAST_NAME' | translate }}</mat-label>\n <input\n matInput\n [appAutofocus]=\"true\"\n [autofocusDelay]=\"500\"\n formControlName=\"lastName\"\n autocomplete=\"section-blue family-name\"\n required\n />\n <mat-error\n *ngIf=\"form.controls.lastName.hasError('required') && form.controls.lastName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.lastName.hasError('minlength') && form.controls.lastName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- First name -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'USER.FIRST_NAME' | translate }}</mat-label>\n <input matInput formControlName=\"firstName\" autocomplete=\"section-blue given-name\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('required') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('minlength') && form.controls.firstName.dirty\">\n <span>{{ 'ERROR.FIELD_MIN_LENGTH' | translate: { requiredLength: 2 } }}</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- Additional fields -->\n @for (definition of additionalFields; track definition.key) {\n <ion-item lines=\"none\">\n <app-form-field\n [definition]=\"definition\"\n [formControlName]=\"definition.key\"\n [required]=\"\n (definition.extra && definition.extra.account && definition.extra.account.required) || false\n \"\n ></app-form-field>\n </ion-item>\n }\n </ion-list>\n\n <!-- Security -->\n @if (showSecurityDetails) {\n <ion-list-header><h3 translate>ACCOUNT.SECURITY.TITLE</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <ion-item\n [button]=\"mobile\"\n routerDirection=\"forward\"\n lines=\"none\"\n (click)=\"openChangePasswordPage()\"\n [disabled]=\"disabled\"\n >\n @if (!mobile) {\n <ion-icon slot=\"start\" name=\"keypad\"></ion-icon>\n <ion-label>{{ 'ACCOUNT.SECURITY.PASSWORD' | translate }}</ion-label>\n }\n <ion-text color=\"tertiary\">{{ 'ACCOUNT.SECURITY.BTN_CHANGE_PASSWORD' | translate }}</ion-text>\n @if (!mobile) {\n <ion-icon slot=\"end\" color=\"tertiary\" name=\"chevron-forward\"></ion-icon>\n }\n </ion-item>\n </ion-list>\n }\n\n <!-- Technical details -->\n @if (showTechnicalDetails) {\n <ion-list-header><h3 translate>ACCOUNT.USER_DETAILS.TECHNICAL_DIVIDER</h3></ion-list-header>\n\n <ion-list [inset]=\"mobile\">\n <!-- profile -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PROFILE' | translate }}</mat-label>\n <input matInput hidden readonly=\"true\" formControlName=\"mainProfile\" required />\n <span>{{ 'USER.PROFILE_ENUM.' + form.controls.mainProfile.value | translate }}</span>\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('mainProfile') && form.controls.mainProfile.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n </ion-item>\n\n <!-- pubkey -->\n <ion-item lines=\"none\">\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.USER_DETAILS.PUBKEY' | translate }}</mat-label>\n <input matInput readonly=\"true\" formControlName=\"pubkey\" required />\n <mat-error\n *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n <mat-error *ngIf=\"form.controls.firstName.hasError('pubkey') && form.controls.firstName.dirty\">\n <span translate>ERROR.FIELD_NOT_VALID_PUBKEY</span>\n </mat-error>\n </mat-form-field>\n </ion-item>\n </ion-list>\n }\n </ion-col>\n\n <!-- right margin -->\n <ion-col size=\"0\" size-lg=\"1\" size-xl=\"2\"> </ion-col>\n </ion-row>\n </ion-grid>\n </mat-tab>\n\n <!-- TAB: settings -->\n <mat-tab [label]=\"'ACCOUNT.SETTINGS.TITLE' | translate\" formGroupName=\"settings\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"settings\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.SETTINGS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.SETTINGS.DESCRIPTION' | translate\"></p>\n\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LOCALE' | translate }}</mat-label>\n <mat-select formControlName=\"locale\" required>\n <mat-option *ngFor=\"let item of locales\" [value]=\"item.key\">\n {{ item.value }}\n </mat-option>\n </mat-select>\n <mat-error\n *ngIf=\"settingsForm?.controls.locale.hasError('required') && settingsForm?.controls.locale.dirty\"\n translate\n >\n ERROR.FIELD_REQUIRED\n </mat-error>\n </mat-form-field>\n\n <!-- lat/long format-->\n @if (showLatLonFormat) {\n @let control = settingsForm | formGetControl: 'latLongFormat';\n <mat-form-field>\n <mat-label>{{ 'ACCOUNT.SETTINGS.LAT_LONG_FORMAT' | translate }}</mat-label>\n <mat-select [formControl]=\"control\" required>\n @for (item of latLongFormats; track item) {\n <mat-option [value]=\"item\">\n {{ 'COMMON.LAT_LONG.ENUM.' + item | uppercase | translate }}\n </mat-option>\n }\n </mat-select>\n @if (control.dirty && control.hasError('required')) {\n <mat-error translate>ERROR.FIELD_REQUIRED</mat-error>\n }\n </mat-form-field>\n }\n </div>\n\n <!-- Options table -->\n <div class=\"options-table\" [class.cdk-visually-hidden]=\"optionDefinitions | isEmptyArray\">\n <app-properties-table\n #propertiesTable\n i18nColumnPrefix=\"ACCOUNT.SETTINGS.OPTIONS.\"\n [definitions]=\"optionDefinitions\"\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-properties-table>\n </div>\n </mat-tab>\n\n <!-- TAB: tokens -->\n <mat-tab [label]=\"'ACCOUNT.TOKENS.TITLE' | translate\" formGroupName=\"tokens\" [disabled]=\"!showApiTokens\">\n <ng-template mat-tab-label>\n <mat-icon>\n <ion-icon matPrefix slot=\"start\" name=\"ticket\"></ion-icon>\n </mat-icon>\n <ion-label translate>ACCOUNT.TOKENS.TITLE</ion-label>\n </ng-template>\n\n <div class=\"ion-padding\">\n <p [innerHTML]=\"'ACCOUNT.TOKENS.DESCRIPTION' | translate\"></p>\n </div>\n <!-- Tokens table -->\n <div class=\"tokens-table\">\n <app-user-token-table\n #tokensTable\n [disabled]=\"disabled\"\n [canEdit]=\"true\"\n [debug]=\"debug\"\n (onDirty)=\"$event ? markAsDirty() : undefined\"\n ></app-user-token-table>\n </div>\n </mat-tab>\n </mat-tab-group>\n </form>\n</ion-content>\n\n<ion-footer hidden-xs hidden-sm hidden-mobile>\n <app-form-buttons-bar (onCancel)=\"cancel()\" (onSave)=\"save()\" [disabled]=\"!form.dirty || !valid || saving\">\n <!-- error -->\n <ion-item *ngIf=\"error && !mobile\" lines=\"none\">\n <ion-icon color=\"danger\" slot=\"start\" name=\"alert-circle\"></ion-icon>\n <ion-label color=\"danger\" class=\"error\" [innerHTML]=\"error | translate\"></ion-label>\n </ion-item>\n </app-form-buttons-bar>\n</ion-footer>\n", styles: ["mat-tab-group .mat-tab-body-content{padding:var(--ion-grid-padding);display:grid}form{width:100%}form mat-form-field{width:100%}.user-avatar{-webkit-background-size:cover;-moz-background-size:cover;-o-background-size:cover;background-size:cover;background-repeat:no-repeat;background-position:center;background-color:var(--ion-color-secondary);overflow:hidden!important;font-size:var(--avatar-size, 96px)!important;line-height:var(--avatar-size, 96px);height:var(--avatar-size, 96px)!important;width:var(--avatar-size, 96px)!important;border:solid 1px rgba(var(--ion-color-secondary-rgb),.5);border-radius:50%;display:inline-block}.user-avatar ion-icon{position:fixed;left:0;bottom:16px;width:var(--avatar-size, 96px)}.user-avatar .visible-hover{display:none;visibility:hidden}.user-avatar:hover{background-color:rgba(var(--ion-color-secondary-rgb),.8);border:solid 2px var(--ion-color-secondary-shade);cursor:pointer}.user-avatar:hover .visible-hover{display:inline;visibility:visible}div.options-table{height:calc(100vh - 380px)}div.tokens-table{height:calc(100vh - 250px)}\n"] }]
|
|
385
402
|
}], ctorParameters: () => [{ type: i0.Injector }, { type: i1.UntypedFormBuilder }, { type: i2.AccountService }, { type: i3.NetworkService }, { type: i4.NavController }, { type: i5.AccountValidatorService }, { type: i6.ConfigService }, { type: i0.ChangeDetectorRef }, { type: i7.ImageService }, { type: i26.Environment, decorators: [{
|
|
386
403
|
type: Inject,
|
|
387
404
|
args: [ENVIRONMENT]
|
|
@@ -406,4 +423,4 @@ i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.13", ngImpo
|
|
|
406
423
|
type: HostListener,
|
|
407
424
|
args: ['window:beforeunload', ['$event']]
|
|
408
425
|
}] } });
|
|
409
|
-
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3VudC5wYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL2FjY291bnQvYWNjb3VudC5wYWdlLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL2FjY291bnQvYWNjb3VudC5wYWdlLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFxQixTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFDbEYsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUVuRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUQsT0FBTyxFQUF3QyxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVsRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBRTVELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsV0FBVyxFQUErQixNQUFNLGtDQUFrQyxDQUFDO0FBRTVGLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHN0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDckUsT0FBTyxFQUFzQixjQUFjLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUV6RixPQUFPLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU9wRixPQUFPLEVBQUUsV0FBVyxFQUFlLE1BQU0seUNBQXlDLENBQUM7QUFDbkYsT0FBTyxFQUFFLGFBQWEsRUFBRSxNQUFNLGlCQUFpQixDQUFDO0FBQ2hELE9BQU8sRUFBRSxXQUFXLEVBQUUsTUFBTSxnQ0FBZ0MsQ0FBQzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7OztBQVE3RCxNQUFNLE9BQU8sV0FBWSxTQUFRLE9BQWdCO0lBb0R0QztJQUNBO0lBQ0E7SUFDRztJQUNBO0lBQ0E7SUFDQTtJQUNBO0lBR21DO0lBN0ROLFFBQVEsQ0FBYztJQUNmLGVBQWUsQ0FBcUI7SUFDeEMsV0FBVyxDQUFpQjtJQUU5RCxnQkFBZ0IsR0FBRyxDQUFDLENBQUM7SUFDckIsT0FBTyxDQUFVO0lBQ2pCLG1CQUFtQixDQUFlO0lBQ2xDLG1CQUFtQixDQUFlO0lBQ2xDLEtBQUssR0FBRztRQUNoQixTQUFTLEVBQUUsS0FBSztRQUNoQixZQUFZLEVBQUUsS0FBSztRQUNuQixPQUFPLEVBQUUsS0FBSztRQUNkLEtBQUssRUFBRSxTQUFTO0tBQ2pCLENBQUM7SUFDUSxnQkFBZ0IsQ0FBd0I7SUFDeEMsaUJBQWlCLENBQXdCO0lBRW5ELElBQUksWUFBWTtRQUNkLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxHQUFHLENBQUMsVUFBVSxDQUFxQixDQUFDO0lBQ3ZELENBQUM7SUFFRCx5Q0FBeUM7SUFDL0IsT0FBTyxDQUFpQjtJQUN4QixjQUFjLEdBQUcsaUJBQWlCLENBQUM7SUFDbkMsTUFBTSxHQUFHLEtBQUssQ0FBQztJQUNmLFNBQVMsR0FBRyxLQUFLLENBQUM7SUFDbEIsZUFBZSxHQUFHLEtBQUssQ0FBQztJQUNmLGtCQUFrQixHQUFHLFdBQVcsQ0FBQyxvQkFBb0IsQ0FBQztJQUN0RCxNQUFNLENBQVU7SUFFbkMsSUFBSSxLQUFLO1FBQ1AsT0FBTyxLQUFLLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLGVBQWUsRUFBRSxLQUFLLElBQUksSUFBSSxDQUFDLENBQUM7SUFDOUQsQ0FBQztJQUVELElBQUksT0FBTztRQUNULE9BQU8sS0FBSyxDQUFDLE9BQU8sSUFBSSxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsQ0FBQyxDQUFDLElBQUksQ0FBQyxlQUFlLENBQUMsT0FBTyxDQUFDLENBQUMsQ0FBQyxLQUFLLENBQUMsQ0FBQztJQUN4RixDQUFDO0lBRUQsSUFBSSxLQUFLO1FBQ1AsT0FBTyxLQUFLLENBQUMsS0FBSyxJQUFJLElBQUksQ0FBQyxlQUFlLEVBQUUsS0FBSyxJQUFJLEtBQUssQ0FBQztJQUM3RCxDQUFDO0lBRVMsZ0JBQWdCLEdBQUcsSUFBSSxDQUFDO0lBQ3hCLGlCQUFpQixHQUFHLEtBQUssQ0FBQztJQUMxQixtQkFBbUIsR0FBRyxLQUFLLENBQUM7SUFDNUIsb0JBQW9CLEdBQUcsSUFBSSxDQUFDO0lBQzVCLGFBQWEsR0FBRyxLQUFLLENBQUM7SUFDdEIsVUFBVSxHQUFHLEtBQUssQ0FBQztJQUU3QixZQUNFLFFBQWtCLEVBQ1gsV0FBK0IsRUFDL0IsY0FBOEIsRUFDOUIsT0FBdUIsRUFDcEIsYUFBNEIsRUFDNUIsZ0JBQXlDLEVBQ3pDLGFBQTRCLEVBQzVCLEVBQXFCLEVBQ3JCLFlBQTBCLEVBQ2YsV0FBd0IsRUFDeEIsT0FBdUIsRUFDQyxXQUFtQjtRQUVoRSxLQUFLLENBQUMsUUFBUSxFQUFFLGdCQUFnQixDQUFDLFlBQVksQ0FBQyxjQUFjLENBQUMsT0FBTyxFQUFFLEVBQUUsWUFBWSxFQUFFLElBQUksRUFBRSxDQUFDLENBQUMsQ0FBQztRQVp4RixnQkFBVyxHQUFYLFdBQVcsQ0FBb0I7UUFDL0IsbUJBQWMsR0FBZCxjQUFjLENBQWdCO1FBQzlCLFlBQU8sR0FBUCxPQUFPLENBQWdCO1FBQ3BCLGtCQUFhLEdBQWIsYUFBYSxDQUFlO1FBQzVCLHFCQUFnQixHQUFoQixnQkFBZ0IsQ0FBeUI7UUFDekMsa0JBQWEsR0FBYixhQUFhLENBQWU7UUFDNUIsT0FBRSxHQUFGLEVBQUUsQ0FBbUI7UUFDckIsaUJBQVksR0FBWixZQUFZLENBQWM7UUFHUyxnQkFBVyxHQUFYLFdBQVcsQ0FBUTtRQUloRSxJQUFJLENBQUMsT0FBTyxHQUFHLE9BQU8sQ0FBQztRQUN2QixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDO1FBQ25DLElBQUksQ0FBQyxLQUFLLEdBQUcsQ0FBQyxXQUFXLENBQUMsVUFBVSxDQUFDO1FBRXJDLCtCQUErQjtRQUMvQixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7SUFDakIsQ0FBQztJQUVELFFBQVE7UUFDTixLQUFLLENBQUMsUUFBUSxFQUFFLENBQUM7UUFFakIsbUJBQW1CO1FBQ25CLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsVUFBVSxJQUFJLEVBQUUsQ0FBQyxDQUFDLE1BQU0sQ0FDcEUsQ0FBQyxVQUFVLEVBQUUsRUFBRSxDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsSUFBSSxDQUFDLENBQUMsVUFBVSxDQUFDLFVBQVUsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLGFBQWEsQ0FBQyxVQUFVLENBQUMsVUFBVSxDQUFDLENBQUMsQ0FDN0gsQ0FBQztRQUVGLHVCQUF1QjtRQUN2QixJQUFJLENBQUMsb0JBQW9CLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLE1BQU0sQ0FBQyxHQUFHLEVBQUUsQ0FBQyxDQUFDLElBQUksQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLE9BQU8sQ0FBQyxPQUFPLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFDdEksSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxjQUFjLENBQUMsUUFBUSxDQUFDLFNBQVMsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUMsQ0FBQyxDQUFDO1FBQ3pGLElBQUksQ0FBQyxvQkFBb0IsQ0FDdkIsSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLENBQUMsR0FBRyxFQUFFO1lBQzNCLElBQUksQ0FBQyxRQUFRLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUMzQyxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7UUFDeEIsQ0FBQyxDQUFDLENBQ0gsQ0FBQztRQUVGLElBQUksQ0FBQyxvQkFBb0IsQ0FDdkIsSUFBSSxDQUFDLGNBQWMsQ0FBQyxpQkFBaUIsQ0FBQyxTQUFTLENBQUMsQ0FBQyxnQkFBZ0IsRUFBRSxFQUFFO1lBQ25FLElBQUksQ0FBQyxnQkFBZ0IsR0FBRyxnQkFBZ0IsQ0FBQyxNQUFNLENBQUMsQ0FBQyxLQUFLLEVBQUUsRUFBRSxDQUFDLEtBQUssQ0FBQyxLQUFLLEVBQUUsT0FBTyxDQUFDLENBQUM7WUFDakYsSUFBSSxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sRUFBRSxFQUFFLENBQUM7Z0JBQ2xDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsQ0FBQztZQUM1QyxDQUFDO2lCQUFNLENBQUM7Z0JBQ04sSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1lBQ3RCLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FDSCxDQUFDO1FBRUYsSUFBSSxDQUFDLG9CQUFvQixDQUFDLElBQUksQ0FBQyxhQUFhLENBQUMsTUFBTSxDQUFDLFNBQVMsQ0FBQyxDQUFDLE1BQU0sRUFBRSxFQUFFLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQyxDQUFDLENBQUM7UUFFeEcsdUZBQXVGO1FBQ3ZGLFVBQVUsQ0FBQyxHQUFHLEVBQUUsQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLGFBQWEsRUFBRSxFQUFFLEdBQUcsQ0FBQyxDQUFDO0lBQ3ZELENBQUM7SUFFRCxLQUFLLENBQUMsY0FBYyxDQUFDLEtBQVk7UUFDL0IsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLElBQUksS0FBSyxDQUFDLGdCQUFnQjtZQUFFLE9BQU87UUFFdkQsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDO1FBQ3ZCLEtBQUssQ0FBQyxlQUFlLEVBQUUsQ0FBQztRQUV4QixJQUFJLENBQUM7WUFDSCxNQUFNLE1BQU0sR0FBRyxNQUFNLElBQUksQ0FBQyxZQUFZLENBQUMsR0FBRyxDQUFDLEtBQUssRUFBRSxFQUFFLFFBQVEsRUFBRSxLQUFLLEVBQUUsZ0JBQWdCLEVBQUUsSUFBSSxFQUFFLEtBQUssRUFBRSxRQUFRLEVBQUUsQ0FBQyxDQUFDO1lBQ2hILE1BQU0sR0FBRyxHQUFHLGVBQWUsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUNwQyxJQUFJLENBQUMsR0FBRyxFQUFFLE9BQU87Z0JBQUUsT0FBTztZQUMxQixNQUFNLE9BQU8sR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEdBQUcsQ0FBQyxRQUFRLENBQUMsQ0FBQztZQUN4QyxJQUFJLE9BQU8sRUFBRSxDQUFDO2dCQUNaLE9BQU8sQ0FBQyxRQUFRLENBQUMsR0FBRyxDQUFDLE9BQU8sQ0FBQyxDQUFDO2dCQUM5QixPQUFPLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDeEIsQ0FBQztpQkFBTSxDQUFDO2dCQUNOLCtEQUErRDtnQkFDL0QsSUFBSSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsRUFBRSxNQUFNLEVBQUUsR0FBRyxDQUFDLE9BQU8sRUFBRSxDQUFDLENBQUM7Z0JBQzlDLElBQUksQ0FBQyxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDMUIsQ0FBQztZQUNELElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztRQUN0QixDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsd0NBQXdDLEVBQUUsR0FBRyxFQUFFLE9BQU8sSUFBSSxHQUFHLENBQUMsQ0FBQztRQUMvRSxDQUFDO0lBQ0gsQ0FBQztJQUVELFdBQVc7UUFDVCxLQUFLLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDcEIsSUFBSSxDQUFDLGlCQUFpQixFQUFFLENBQUM7UUFDekIsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDO0lBQzFDLENBQUM7SUFFRCxPQUFPLENBQUMsT0FBZ0I7UUFDdEIsT0FBTyxDQUFDLEtBQUssQ0FBQyw0QkFBNEIsRUFBRSxPQUFPLENBQUMsQ0FBQztRQUNyRCxJQUFJLENBQUMsT0FBTyxHQUFHLElBQUksQ0FBQztRQUVwQixJQUFJLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxDQUFDO1FBRXZCLElBQUksQ0FBQyxLQUFLLENBQUMsU0FBUyxHQUFHLE9BQU8sSUFBSSxPQUFPLENBQUMsS0FBSyxJQUFJLE9BQU8sQ0FBQyxRQUFRLEtBQUssU0FBUyxDQUFDLFNBQVMsQ0FBQztRQUM1RixJQUFJLENBQUMsS0FBSyxDQUFDLFlBQVksR0FBRyxPQUFPLElBQUksT0FBTyxDQUFDLEtBQUssSUFBSSxDQUFDLENBQUMsT0FBTyxDQUFDLFFBQVEsSUFBSSxPQUFPLENBQUMsUUFBUSxLQUFLLFNBQVMsQ0FBQyxTQUFTLENBQUMsQ0FBQztRQUV0SCxJQUFJLENBQUMsbUJBQW1CLEVBQUUsV0FBVyxFQUFFLENBQUM7UUFDeEMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLGFBQWEsQ0FBQztZQUN2QyxJQUFJLENBQUMsYUFBYSxDQUFDLE1BQU07WUFDekIsSUFBSSxDQUFDLE9BQU8sQ0FBQyxzQkFBc0IsQ0FBQyxJQUFJLENBQUMsR0FBRyxDQUFDLENBQUMsY0FBYyxFQUFFLEVBQUUsQ0FBQyxjQUFjLEtBQUssTUFBTSxDQUFDLENBQUM7U0FDN0YsQ0FBQyxDQUFDLFNBQVMsQ0FBQyxDQUFDLENBQUMsTUFBTSxFQUFFLE1BQU0sQ0FBQyxFQUFFLEVBQUU7WUFDaEMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLENBQUMsQ0FBQztZQUU1QixJQUFJLE1BQU0sRUFBRSxDQUFDO2dCQUNYLElBQUksQ0FBQyxNQUFNLEVBQUUsQ0FBQztnQkFDZCxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7Z0JBQ3RCLElBQUksQ0FBQyxrQkFBa0IsRUFBRSxDQUFDO1lBQzVCLENBQUM7aUJBQU0sQ0FBQztnQkFDTixJQUFJLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ2YsSUFBSSxDQUFDLGNBQWMsRUFBRSxDQUFDO2dCQUN0QixJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQztZQUMzQixDQUFDO1lBQ0QsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO1FBQ3RCLENBQUMsQ0FBQyxDQUFDO1FBRUgsSUFBSSxDQUFDLFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFRCxRQUFRO1FBQ04sSUFBSSxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDckIsSUFBSSxDQUFDLEtBQUssQ0FBQyxTQUFTLEdBQUcsS0FBSyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLENBQUMsWUFBWSxHQUFHLEtBQUssQ0FBQztRQUNoQyxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBQzdCLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7UUFDbEIsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRWYsSUFBSSxDQUFDLG1CQUFtQixFQUFFLFdBQVcsRUFBRSxDQUFDO1FBRXhDLElBQUksQ0FBQyxpQkFBaUIsRUFBRSxDQUFDO1FBRXpCLGVBQWU7UUFDZixJQUFJLENBQUMsYUFBYSxDQUFDLFlBQVksQ0FBQyxHQUFHLENBQUMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFhLEVBQUUsSUFBa0Q7UUFDOUUsS0FBSyxDQUFDLFFBQVEsQ0FBQyxJQUFJLEVBQUUsSUFBSSxDQUFDLENBQUM7UUFFM0IsY0FBYztRQUNkLE1BQU0sRUFBRSxVQUFVLEVBQUUsR0FBRyxJQUFJLEVBQUUsUUFBUSxFQUFFLGVBQWUsQ0FBQyxFQUFFLFdBQVcsRUFBRSxJQUFJLENBQUMsaUJBQWlCLEVBQUUsQ0FBQyxJQUFJLEVBQUUsQ0FBQztRQUN0RyxNQUFNLGtCQUFrQixHQUFxQixJQUFJLENBQUMsaUJBQWlCO2FBQ2hFLEdBQUcsQ0FBQyxDQUFDLFVBQVUsRUFBRSxFQUFFO1lBQ2xCLE1BQU0sS0FBSyxHQUFHLFVBQVUsRUFBRSxDQUFDLFVBQVUsQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUMzQyxPQUFPLFFBQVEsQ0FBQyxLQUFLLENBQUMsQ0FBQyxDQUFDLENBQUMsY0FBYyxDQUFDLFVBQVUsQ0FBQyxFQUFFLFVBQVUsRUFBRSxLQUFLLEVBQUUsQ0FBQyxDQUFDLENBQUMsQ0FBQyxJQUFJLENBQUM7UUFDbkYsQ0FBQyxDQUFDO2FBQ0QsTUFBTSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1FBRXBCLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3pCLE1BQU0sSUFBSSxDQUFDLGVBQWUsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUNuQyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssR0FBRyxrQkFBa0IsQ0FBQztRQUNsRCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLEtBQUssRUFBRSxDQUFDO1lBQy9CLElBQUksQ0FBQyxXQUFXLENBQUMsS0FBSyxHQUFHLElBQUksQ0FBQyxNQUFNLENBQUM7UUFDdkMsQ0FBQztJQUNILENBQUM7SUFFRCxLQUFLLENBQUMsT0FBTyxDQUFDLENBQVM7UUFDckIsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2YsSUFBSSxDQUFDLGFBQWEsRUFBRSxDQUFDO1FBRXJCLE9BQU8sSUFBSSxDQUFDLGNBQWMsQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN0QyxDQUFDO0lBRUQsa0JBQWtCO1FBQ2hCLElBQUksSUFBSSxDQUFDLG1CQUFtQjtZQUFFLE9BQU8sQ0FBQyxrQkFBa0I7UUFDeEQsSUFBSSxDQUFDLG1CQUFtQixHQUFHLElBQUksQ0FBQyxjQUFjLENBQUMsYUFBYSxFQUFFLENBQUM7SUFDakUsQ0FBQztJQUVELGlCQUFpQjtRQUNmLElBQUksQ0FBQyxJQUFJLENBQUMsbUJBQW1CO1lBQUUsT0FBTztRQUN0QyxJQUFJLENBQUMsbUJBQW1CLENBQUMsV0FBVyxFQUFFLENBQUM7UUFDdkMsSUFBSSxDQUFDLG1CQUFtQixHQUFHLFNBQVMsQ0FBQztJQUN2QyxDQUFDO0lBRUQsS0FBSyxDQUFDLHFCQUFxQixDQUFDLEtBQWlCO1FBQzNDLE1BQU0sSUFBSSxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxDQUFDO1FBQzdCLElBQUksQ0FBQyxLQUFLLEdBQUcsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsT0FBTyxDQUFDLENBQUMsS0FBSyxDQUFDO1FBQy9DLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUssQ0FBQyxZQUFZLEVBQUUsQ0FBQztZQUM1QyxLQUFLLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdkIsT0FBTyxLQUFLLENBQUM7UUFDZixDQUFDO1FBRUQsSUFBSSxDQUFDLEtBQUssQ0FBQyxPQUFPLEdBQUcsSUFBSSxDQUFDO1FBQzFCLE9BQU8sQ0FBQyxLQUFLLENBQUMseUNBQXlDLENBQUMsQ0FBQztRQUN6RCxJQUFJLENBQUM7WUFDSCxNQUFNLElBQUksQ0FBQyxjQUFjLENBQUMscUJBQXFCLENBQUMsSUFBSSxDQUFDLEtBQUssRUFBRSxDQUFDLElBQUksQ0FBQyxRQUFRLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxNQUFNLENBQUMsSUFBSSxJQUFJLENBQUMsU0FBUyxDQUFDLFdBQVcsQ0FBQyxDQUFDO1lBQ25JLE9BQU8sQ0FBQyxLQUFLLENBQUMsb0NBQW9DLENBQUMsQ0FBQztZQUNwRCxJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7UUFDN0IsQ0FBQztRQUFDLE9BQU8sR0FBRyxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsS0FBSyxDQUFDLE9BQU8sR0FBRyxLQUFLLENBQUM7WUFDM0IsSUFBSSxDQUFDLEtBQUssQ0FBQyxLQUFLLEdBQUcsQ0FBQyxHQUFHLElBQUksR0FBRyxDQUFDLE9BQU8sQ0FBQyxJQUFJLEdBQUcsQ0FBQztRQUNqRCxDQUFDO0lBQ0gsQ0FBQztJQUVELEtBQUssQ0FBQyxJQUFJLENBQUMsS0FBYTtRQUN0QixJQUFJLElBQUksQ0FBQyxNQUFNO1lBQUUsT0FBTyxLQUFLLENBQUM7UUFFOUIsSUFBSSxDQUFDLElBQUksQ0FBQyxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDckIsTUFBTSxZQUFZLENBQUMsZ0JBQWdCLENBQUMsSUFBSSxDQUFDLElBQUksQ0FBQyxDQUFDO1lBRS9DLElBQUksSUFBSSxDQUFDLElBQUksQ0FBQyxPQUFPLEVBQUUsQ0FBQztnQkFDdEIsWUFBWSxDQUFDLGFBQWEsQ0FBQyxJQUFJLENBQUMsSUFBSSxDQUFDLENBQUM7Z0JBQ3RDLElBQUksQ0FBQyxJQUFJLENBQUMsZ0JBQWdCLEVBQUUsQ0FBQztnQkFDN0IsT0FBTyxLQUFLLENBQUM7WUFDZixDQUFDO1FBQ0gsQ0FBQztRQUVELElBQUksQ0FBQyxTQUFTLEdBQUcsSUFBSSxDQUFDO1FBQ3RCLElBQUksQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDO1FBQ25CLElBQUksQ0FBQyxLQUFLLEdBQUcsU0FBUyxDQUFDO1FBRXZCLE1BQU0sVUFBVSxHQUFHLE9BQU8sQ0FBQyxVQUFVLENBQUM7WUFDcEMsR0FBRyxJQUFJLENBQUMsY0FBYyxDQUFDLE9BQU8sQ0FBQyxRQUFRLEVBQUU7WUFDekMsR0FBRyxJQUFJLENBQUMsSUFBSSxDQUFDLEtBQUs7U0FDbkIsQ0FBQyxDQUFDO1FBRUgsSUFBSSxlQUFlLENBQUMsSUFBSSxDQUFDLGlCQUFpQixDQUFDLElBQUksSUFBSSxDQUFDLGVBQWUsRUFBRSxDQUFDO1lBQ3BFLG1CQUFtQjtZQUNuQixNQUFNLElBQUksQ0FBQyxlQUFlLENBQUMsSUFBSSxFQUFFLENBQUM7WUFDbEMsTUFBTSxnQkFBZ0IsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDLEtBQUssSUFBSSxFQUFFLENBQUM7WUFDMUQsTUFBTSxVQUFVLEdBQWdCLGdCQUFnQixDQUFDLE1BQU0sQ0FBQyxDQUFDLEdBQUcsRUFBRSxJQUFJLEVBQUUsRUFBRTtnQkFDcEUsR0FBRyxDQUFDLElBQUksQ0FBQyxFQUFFLENBQUMsR0FBRyxJQUFJLENBQUMsS0FBSyxDQUFDO2dCQUMxQixPQUFPLEdBQUcsQ0FBQztZQUNiLENBQUMsRUFBRSxFQUFFLENBQUMsQ0FBQztZQUNQLE1BQU0sYUFBYSxHQUFHLEVBQUUsR0FBRyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsRUFBRSxHQUFHLFVBQVUsRUFBRSxDQUFDO1lBQ3RGLFVBQVUsQ0FBQyxRQUFRLENBQUMsS0FBSyxDQUFnQixFQUFFLFVBQVUsRUFBRSxhQUFhLEVBQUUsRUFBRSxDQUFDLFlBQVksQ0FBQyxDQUFDLENBQUM7UUFDMUYsQ0FBQzthQUFNLElBQUksVUFBVSxDQUFDLFFBQVEsQ0FBQyxPQUFPLENBQUMsWUFBWSxDQUFDLEVBQUUsQ0FBQztZQUNyRCxtQkFBbUI7WUFDbkIsT0FBTyxVQUFVLENBQUMsUUFBUSxDQUFDLE9BQU8sQ0FBQyxZQUFZLENBQUMsQ0FBQztRQUNuRCxDQUFDO1FBRUQsSUFBSSxJQUFJLENBQUMsV0FBVyxFQUFFLENBQUM7WUFDckIsTUFBTSxJQUFJLENBQUMsV0FBVyxDQUFDLElBQUksRUFBRSxDQUFDO1lBQzlCLFVBQVUsQ0FBQyxNQUFNLEdBQUcsSUFBSSxDQUFDLFdBQVcsQ0FBQyxLQUFLLENBQUM7UUFDN0MsQ0FBQztRQUVELE9BQU8sQ0FBQyxLQUFLLENBQUMsNkJBQTZCLEVBQUUsVUFBVSxDQUFDLENBQUM7UUFDekQsSUFBSSxDQUFDO1lBQ0gsSUFBSSxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBRWYsTUFBTSxJQUFJLENBQUMsY0FBYyxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQztZQUUzQyxTQUFTO1lBQ1QsVUFBVSxDQUFDLEdBQUcsRUFBRSxDQUFDLElBQUksQ0FBQyxPQUFPLENBQUMsSUFBSSxDQUFDLGNBQWMsQ0FBQyxPQUFPLENBQUMsRUFBRSxHQUFHLENBQUMsQ0FBQztZQUVqRSxJQUFJLENBQUMsY0FBYyxFQUFFLENBQUM7WUFDdEIsT0FBTyxJQUFJLENBQUM7UUFDZCxDQUFDO1FBQUMsT0FBTyxHQUFHLEVBQUUsQ0FBQztZQUNiLE9BQU8sQ0FBQyxLQUFLLENBQUMsR0FBRyxDQUFDLENBQUM7WUFDbkIsSUFBSSxDQUFDLEtBQUssR0FBRyxDQUFDLEdBQUcsSUFBSSxHQUFHLENBQUMsT0FBTyxDQUFDLElBQUksR0FBRyxDQUFDO1lBQ3pDLE9BQU8sS0FBSyxDQUFDO1FBQ2YsQ0FBQztnQkFBUyxDQUFDO1lBQ1QsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7WUFDcEIsSUFBSSxDQUFDLE1BQU0sRUFBRSxDQUFDO1FBQ2hCLENBQUM7SUFDSCxDQUFDO0lBRUQsTUFBTSxDQUFDLElBQWtEO1FBQ3ZELEtBQUssQ0FBQyxNQUFNLENBQUMsSUFBSSxDQUFDLENBQUM7UUFFbkIsaUNBQWlDO1FBQ2pDLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxPQUFPLEVBQUUsQ0FBQztRQUNuQyxJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxXQUFXLENBQUMsT0FBTyxFQUFFLENBQUM7UUFDekMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsTUFBTSxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBRXBDLHNEQUFzRDtRQUN0RCxNQUFNLFFBQVEsR0FBRyxJQUFJLENBQUMsZUFBZSxDQUFDO1FBQ3RDLElBQUksUUFBUSxFQUFFLENBQUM7WUFDYixJQUFJLENBQUMsSUFBSSxDQUFDLFFBQVEsQ0FBQyxRQUFRLENBQUMsT0FBTyxFQUFFLENBQUM7WUFDdEMsSUFBSSxDQUFDLElBQUksQ0FBQyxRQUFRLENBQUMsU0FBUyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ3pDLENBQUM7UUFFRCx3Q0FBd0M7UUFDeEMsSUFBSSxDQUFDLGdCQUFnQixDQUFDLE9BQU8sQ0FBQyxDQUFDLEtBQUssRUFBRSxFQUFFO1lBQ3RDLE1BQU0sT0FBTyxHQUFHLElBQUksQ0FBQyxJQUFJLENBQUMsUUFBUSxDQUFDLEtBQUssQ0FBQyxHQUFHLENBQUMsQ0FBQztZQUM5QyxJQUFJLENBQUMsT0FBTztnQkFBRSxPQUFPLENBQUMsT0FBTztZQUU3QixNQUFNLGFBQWEsR0FBRyxRQUFRLElBQUksS0FBSyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxJQUFJLEtBQUssQ0FBQztZQUMxRSxJQUFJLGFBQWEsSUFBSSxPQUFPLENBQUMsT0FBTyxFQUFFLENBQUM7Z0JBQ3JDLE9BQU8sQ0FBQyxPQUFPLEVBQUUsQ0FBQztZQUNwQixDQUFDO1lBQ0QsTUFBTSxRQUFRLEdBQUcsS0FBSyxDQUFDLEtBQUssRUFBRSxPQUFPLEVBQUUsUUFBUSxJQUFJLEtBQUssQ0FBQztZQUN6RCxJQUFJLENBQUMsS0FBSyxDQUFDLFFBQVEsSUFBSSxRQUFRLEVBQUUsQ0FBQztnQkFDaEMsT0FBTyxDQUFDLGFBQWEsQ0FBQyxPQUFPLENBQUMsU0FBUyxDQUFDLENBQUMsQ0FBQyxVQUFVLENBQUMsT0FBTyxDQUFDLENBQUMsT0FBTyxDQUFDLFNBQVMsRUFBRSxVQUFVLENBQUMsUUFBUSxDQUFDLENBQUMsQ0FBQyxDQUFDLENBQUMsVUFBVSxDQUFDLFFBQVEsQ0FBQyxDQUFDO1lBQ2hJLENBQUM7UUFDSCxDQUFDLENBQUMsQ0FBQztRQUNILElBQUksQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN0QixDQUFDO0lBRUQsS0FBSyxDQUFDLE1BQU07UUFDVixNQUFNLEtBQUssQ0FBQyxNQUFNLEVBQUUsQ0FBQztJQUN2QixDQUFDO0lBRUQsS0FBSyxDQUFDLEtBQUssQ0FBQyxDQUFTO1FBQ25CLElBQUksSUFBSSxDQUFDLE1BQU07WUFBRSxPQUFPO1FBRXhCLGVBQWU7UUFDZixPQUFPLElBQUksQ0FBQyxhQUFhLENBQUMsWUFBWSxDQUFDLEdBQUcsQ0FBQyxDQUFDLENBQUMsZUFBZTtJQUM5RCxDQUFDO0lBR0QsYUFBYSxDQUFDLEtBQXdCO1FBQ3BDLGlEQUFpRDtRQUNqRCxJQUFJLENBQUMsSUFBSSxDQUFDLE1BQU0sSUFBSSxJQUFJLENBQUMsS0FBSyxFQUFFLENBQUM7WUFDL0IsS0FBSyxDQUFDLGNBQWMsRUFBRSxDQUFDLENBQUMsK0JBQStCO1FBQ3pELENBQUM7SUFDSCxDQUFDO0lBRVMsY0FBYyxDQUFDLE1BQXFCO1FBQzVDLE9BQU8sQ0FBQyxLQUFLLENBQUMsMkJBQTJCLEVBQUUsTUFBTSxDQUFDLENBQUM7UUFDbkQsSUFBSSxDQUFDLGVBQWUsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsbUJBQW1CLENBQUMsZ0JBQWdCLENBQUMsQ0FBQztRQUN6RixJQUFJLENBQUMsZ0JBQWdCO1lBQ25CLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxtQkFBbUIsQ0FBQyw4QkFBOEIsQ0FBQztnQkFDL0Usd0NBQXdDO2dCQUN4QyxNQUFNLENBQUMsb0JBQW9CLENBQUMsbUJBQW1CLENBQUMsK0JBQStCLENBQUMsQ0FBQztRQUNuRixJQUFJLENBQUMsVUFBVSxHQUFHLE1BQU0sQ0FBQyxvQkFBb0IsQ0FBQyxtQkFBbUIsQ0FBQyxxQkFBcUIsQ0FBQyxDQUFDO1FBRXpGLE1BQU0sYUFBYSxHQUFHLE1BQU0sQ0FBQyxXQUFXLENBQUMsbUJBQW1CLENBQUMsZUFBZSxDQUFrQixDQUFDO1FBQy9GLElBQUksQ0FBQyxpQkFBaUIsR0FBRyxhQUFhLEtBQUssT0FBTyxDQUFDO1FBQ25ELElBQUksQ0FBQyxtQkFBbUIsR0FBRyxJQUFJLENBQUMsaUJBQWlCLENBQUM7UUFDbEQsSUFBSSxDQUFDLGFBQWEsR0FBRyxNQUFNLENBQUMsb0JBQW9CLENBQUMsbUJBQW1CLENBQUMsc0JBQXNCLENBQUMsQ0FBQztRQUM3RixJQUFJLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDdEIsQ0FBQztJQUVTLFlBQVk7UUFDcEIsSUFBSSxDQUFDLEVBQUUsQ0FBQyxZQUFZLEVBQUUsQ0FBQztJQUN6QixDQUFDO0lBRVMsc0JBQXNCO1FBQzlCLElBQUksQ0FBQyxhQUFhLENBQUMsZUFBZSxDQUFDLGtCQUFrQixDQUFDLENBQUM7SUFDekQsQ0FBQzt3R0FqWVUsV0FBVyxzU0E0RFosV0FBVyxhQUNYLFdBQVcsYUFDQyxhQUFhOzRGQTlEeEIsV0FBVywwZUNyQ3hCLDg1ZUEyVkE7OzRGRHRUYSxXQUFXO2tCQU52QixTQUFTOytCQUNFLGtCQUFrQixtQkFHWCx1QkFBdUIsQ0FBQyxNQUFNOzswQkE4RDVDLE1BQU07MkJBQUMsV0FBVzs7MEJBQ2xCLE1BQU07MkJBQUMsV0FBVzs7MEJBQ2xCLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsYUFBYTt5Q0E3RE0sUUFBUTtzQkFBaEQsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNTLGVBQWU7c0JBQTlELFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNGLFdBQVc7c0JBQXRELFNBQVM7dUJBQUMsYUFBYSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkFpVzFDLGFBQWE7c0JBRFosWUFBWTt1QkFBQyxxQkFBcUIsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBIb3N0TGlzdGVuZXIsIEluamVjdCwgSW5qZWN0b3IsIE9uRGVzdHJveSwgT25Jbml0LFxuICBPcHRpb25hbCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFjY291bnRTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvYWNjb3VudC5zZXJ2aWNlJztcbmltcG9ydCB7IEFjY291bnQgfSBmcm9tICcuLi9zZXJ2aWNlcy9tb2RlbC9hY2NvdW50Lm1vZGVsJztcbmltcG9ydCB7IFVudHlwZWRGb3JtQnVpbGRlciwgVW50eXBlZEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFjY291bnRWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvdmFsaWRhdG9yL2FjY291bnQudmFsaWRhdG9yJztcbmltcG9ydCB7IEFwcEZvcm0gfSBmcm9tICcuLi9mb3JtL2Zvcm0uY2xhc3MnO1xuaW1wb3J0IHsgQXBwRm9ybVV0aWxzLCBDYW5MZWF2ZSB9IGZyb20gJy4uL2Zvcm0vZm9ybS51dGlscyc7XG5pbXBvcnQgeyBGb3JtRmllbGREZWZpbml0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2Zvcm0vZmllbGQubW9kZWwnO1xuaW1wb3J0IHsgTEFUX0xPTkdfUEFUVEVSTlMgfSBmcm9tICcuLi8uLi9zaGFyZWQvbWF0ZXJpYWwvbGF0bG9uZy9sYXRsb25nLnV0aWxzJztcbmltcG9ydCB7IFN0YXR1c0lkcyB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL21vZGVsLmVudW0nO1xuaW1wb3J0IHsgQVBQX0xPQ0FMRVMsIExvY2FsZUNvbmZpZywgTG9jYWxTZXR0aW5ncyB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL3NldHRpbmdzLm1vZGVsJztcbmltcG9ydCB7IE5ldHdvcmtTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvbmV0d29yay5zZXJ2aWNlJztcbmltcG9ydCB7IGZpbHRlciwgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgTWF0VGFiR3JvdXAgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcbmltcG9ydCB7IENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9jb25maWcuc2VydmljZSc7XG5pbXBvcnQgeyBDT1JFX0NPTkZJR19PUFRJT05TIH0gZnJvbSAnLi4vc2VydmljZXMvY29uZmlnL2NvcmUuY29uZmlnJztcbmltcG9ydCB7IEFwcFByb3BlcnRpZXNUYWJsZSwgUHJvcGVydHlFbnRpdHkgfSBmcm9tICcuLi9mb3JtL3Byb3BlcnRpZXMvcHJvcGVydGllcy50YWJsZSc7XG5pbXBvcnQgeyBQcm9wZXJ0eU1hcCB9IGZyb20gJy4uLy4uL3NoYXJlZC90eXBlcyc7XG5pbXBvcnQgeyBmaXJzdEFycmF5VmFsdWUsIGlzTm90RW1wdHlBcnJheSwgaXNOb3ROaWwgfSBmcm9tICcuLi8uLi9zaGFyZWQvZnVuY3Rpb25zJztcbmltcG9ydCB7IFVzZXJUb2tlblRhYmxlIH0gZnJvbSAnLi90b2tlbi50YWJsZSc7XG5pbXBvcnQgeyBOYXZDb250cm9sbGVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL2NvbmZpZy5tb2RlbCc7XG5cbmltcG9ydCB7IEF1dGhUb2tlblR5cGUgfSBmcm9tICcuLi9zZXJ2aWNlcy9uZXR3b3JrLnR5cGVzJztcbmltcG9ydCB7IEltYWdlU2VydmljZSB9IGZyb20gJy4uLy4uL3NoYXJlZC9pbWFnZS9pbWFnZS5zZXJ2aWNlJztcbmltcG9ydCB7IEVOVklST05NRU5ULCBFbnZpcm9ubWVudCB9IGZyb20gJy4uLy4uLy4uL2Vudmlyb25tZW50cy9lbnZpcm9ubWVudC5jbGFzcyc7XG5pbXBvcnQgeyBBUFBfQkFTRV9IUkVGIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFBlcnNvblV0aWxzIH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvcGVyc29uLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLWFjY291bnQtcGFnZScsXG4gIHRlbXBsYXRlVXJsOiAnYWNjb3VudC5wYWdlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9hY2NvdW50LnBhZ2Uuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgQWNjb3VudFBhZ2UgZXh0ZW5kcyBBcHBGb3JtPEFjY291bnQ+IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIENhbkxlYXZlIHtcbiAgQFZpZXdDaGlsZCgndGFiR3JvdXAnLCB7IHN0YXRpYzogdHJ1ZSB9KSB0YWJHcm91cDogTWF0VGFiR3JvdXA7XG4gIEBWaWV3Q2hpbGQoJ3Byb3BlcnRpZXNUYWJsZScsIHsgc3RhdGljOiB0cnVlIH0pIHByb3BlcnRpZXNUYWJsZTogQXBwUHJvcGVydGllc1RhYmxlO1xuICBAVmlld0NoaWxkKCd0b2tlbnNUYWJsZScsIHsgc3RhdGljOiB0cnVlIH0pIHRva2Vuc1RhYmxlOiBVc2VyVG9rZW5UYWJsZTtcblxuICBwcm90ZWN0ZWQgc2VsZWN0ZWRUYWJJbmRleCA9IDA7XG4gIHByb3RlY3RlZCBpc0xvZ2luOiBib29sZWFuO1xuICBwcm90ZWN0ZWQgY2hhbmdlc1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBwcm90ZWN0ZWQgbmV0d29ya1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBwcm90ZWN0ZWQgZW1haWwgPSB7XG4gICAgY29uZmlybWVkOiBmYWxzZSxcbiAgICBub3RDb25maXJtZWQ6IGZhbHNlLFxuICAgIHNlbmRpbmc6IGZhbHNlLFxuICAgIGVycm9yOiB1bmRlZmluZWQsXG4gIH07XG4gIHByb3RlY3RlZCBhZGRpdGlvbmFsRmllbGRzOiBGb3JtRmllbGREZWZpbml0aW9uW107XG4gIHByb3RlY3RlZCBvcHRpb25EZWZpbml0aW9uczogRm9ybUZpZWxkRGVmaW5pdGlvbltdO1xuXG4gIGdldCBzZXR0aW5nc0Zvcm0oKTogVW50eXBlZEZvcm1Hcm91cCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybS5nZXQoJ3NldHRpbmdzJykgYXMgVW50eXBlZEZvcm1Hcm91cDtcbiAgfVxuXG4gIC8vIHNldHRpbmdzQ29udGVudEZvcm06IFVudHlwZWRGb3JtR3JvdXA7XG4gIHByb3RlY3RlZCBsb2NhbGVzOiBMb2NhbGVDb25maWdbXTtcbiAgcHJvdGVjdGVkIGxhdExvbmdGb3JtYXRzID0gTEFUX0xPTkdfUEFUVEVSTlM7XG4gIHByb3RlY3RlZCBzYXZpbmcgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIHN1Ym1pdHRlZCA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgYWNjb3VudFJlYWRPbmx5ID0gZmFsc2U7XG4gIHByb3RlY3RlZCByZWFkb25seSBkZWZhdWx0QXZhdGFySW1hZ2UgPSBQZXJzb25VdGlscy5ERUZBVUxUX0FWQVRBUl9JTUFHRTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IG1vYmlsZTogYm9vbGVhbjtcblxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHN1cGVyLnZhbGlkICYmICh0aGlzLnByb3BlcnRpZXNUYWJsZT8udmFsaWQgfHwgdHJ1ZSk7XG4gIH1cblxuICBnZXQgaW52YWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gc3VwZXIuaW52YWxpZCAmJiAodGhpcy5wcm9wZXJ0aWVzVGFibGUgPyB0aGlzLnByb3BlcnRpZXNUYWJsZS5pbnZhbGlkIDogZmFsc2UpO1xuICB9XG5cbiAgZ2V0IGRpcnR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzdXBlci5kaXJ0eSB8fCB0aGlzLnByb3BlcnRpZXNUYWJsZT8uZGlydHkgfHwgZmFsc2U7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd0xhdExvbkZvcm1hdCA9IHRydWU7XG4gIHByb3RlY3RlZCBjYW5DaGFuZ2VQYXNzd29yZCA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgc2hvd1NlY3VyaXR5RGV0YWlscyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgc2hvd1RlY2huaWNhbERldGFpbHMgPSB0cnVlO1xuICBwcm90ZWN0ZWQgc2hvd0FwaVRva2VucyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgc2hvd0F2YXRhciA9IGZhbHNlO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBwdWJsaWMgZm9ybUJ1aWxkZXI6IFVudHlwZWRGb3JtQnVpbGRlcixcbiAgICBwdWJsaWMgYWNjb3VudFNlcnZpY2U6IEFjY291bnRTZXJ2aWNlLFxuICAgIHB1YmxpYyBuZXR3b3JrOiBOZXR3b3JrU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgbmF2Q29udHJvbGxlcjogTmF2Q29udHJvbGxlcixcbiAgICBwcm90ZWN0ZWQgdmFsaWRhdG9yU2VydmljZTogQWNjb3VudFZhbGlkYXRvclNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcm90ZWN0ZWQgaW1hZ2VTZXJ2aWNlOiBJbWFnZVNlcnZpY2UsXG4gICAgQEluamVjdChFTlZJUk9OTUVOVCkgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuICAgIEBJbmplY3QoQVBQX0xPQ0FMRVMpIGxvY2FsZXM6IExvY2FsZUNvbmZpZ1tdLFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoQVBQX0JBU0VfSFJFRikgcHJvdGVjdGVkIGFwcEJhc2VIcmVmOiBzdHJpbmcsXG4gICkge1xuICAgIHN1cGVyKGluamVjdG9yLCB2YWxpZGF0b3JTZXJ2aWNlLmdldEZvcm1Hcm91cChhY2NvdW50U2VydmljZS5hY2NvdW50LCB7IHdpdGhTZXR0aW5nczogdHJ1ZSB9KSk7XG5cbiAgICB0aGlzLmxvY2FsZXMgPSBsb2NhbGVzO1xuICAgIHRoaXMubW9iaWxlID0gdGhpcy5zZXR0aW5ncy5tb2JpbGU7XG4gICAgdGhpcy5kZWJ1ZyA9ICFlbnZpcm9ubWVudC5wcm9kdWN0aW9uO1xuXG4gICAgLy8gQnkgZGVmYXVsdCwgZGlzYWJsZSB0aGUgZm9ybVxuICAgIHRoaXMuZGlzYWJsZSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcblxuICAgIC8vIEdldCB1c2VyIG9wdGlvbnNcbiAgICB0aGlzLm9wdGlvbkRlZmluaXRpb25zID0gKHRoaXMuYWNjb3VudFNlcnZpY2Uub3B0aW9uRGVmcyB8fCBbXSkuZmlsdGVyKFxuICAgICAgKGRlZmluaXRpb24pID0+ICFkZWZpbml0aW9uLmRpc2FibGVkICYmICghZGVmaW5pdGlvbi5taW5Qcm9maWxlIHx8IHRoaXMuYWNjb3VudFNlcnZpY2UuaGFzTWluUHJvZmlsZShkZWZpbml0aW9uLm1pblByb2ZpbGUpKVxuICAgICk7XG5cbiAgICAvLyBPYnNlcnZlZCBzb21lIGV2ZW50c1xuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24odGhpcy5hY2NvdW50U2VydmljZS5vbkxvZ2luLnBpcGUoZmlsdGVyKCgpID0+ICF0aGlzLnNhdmluZykpLnN1YnNjcmliZSgoYWNjb3VudCkgPT4gdGhpcy5vbkxvZ2luKGFjY291bnQpKSk7XG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbih0aGlzLmFjY291bnRTZXJ2aWNlLm9uTG9nb3V0LnN1YnNjcmliZSgoKSA9PiB0aGlzLm9uTG9nb3V0KCkpKTtcbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgdGhpcy5vbkNhbmNlbC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnNldFZhbHVlKHRoaXMuYWNjb3VudFNlcnZpY2UuYWNjb3VudCk7XG4gICAgICAgIHRoaXMubWFya0FzUHJpc3RpbmUoKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLmFjY291bnRTZXJ2aWNlLmFkZGl0aW9uYWxGaWVsZHMkLnN1YnNjcmliZSgoYWRkaXRpb25hbEZpZWxkcykgPT4ge1xuICAgICAgICB0aGlzLmFkZGl0aW9uYWxGaWVsZHMgPSBhZGRpdGlvbmFsRmllbGRzLmZpbHRlcigoZmllbGQpID0+IGZpZWxkLmV4dHJhPy5hY2NvdW50KTtcbiAgICAgICAgaWYgKHRoaXMuYWNjb3VudFNlcnZpY2UuaXNMb2dpbigpKSB7XG4gICAgICAgICAgdGhpcy5vbkxvZ2luKHRoaXMuYWNjb3VudFNlcnZpY2UuYWNjb3VudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5tYXJrQXNMb2FkZWQoKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbih0aGlzLmNvbmZpZ1NlcnZpY2UuY29uZmlnLnN1YnNjcmliZSgoY29uZmlnKSA9PiB0aGlzLm9uQ29uZmlnTG9hZGVkKGNvbmZpZykpKTtcblxuICAgIC8vIFJlYWxpZ24gdGFiLCBhZnRlciBhIGRlbGF5IGJlY2F1c2UgdGhlIHRhYiBjYW4gYmUgZGlzYWJsZWQgd2hlbiBjb21wb25lbnQgaXMgY3JlYXRlZFxuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy50YWJHcm91cC5yZWFsaWduSW5rQmFyKCksIDUwMCk7XG4gIH1cblxuICBhc3luYyBvbkNoYW5nZUF2YXRhcihldmVudDogRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuc2hvd0F2YXRhciB8fCBldmVudC5kZWZhdWx0UHJldmVudGVkKSByZXR1cm47XG5cbiAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgIGV2ZW50LnN0b3BQcm9wYWdhdGlvbigpO1xuXG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IGltYWdlcyA9IGF3YWl0IHRoaXMuaW1hZ2VTZXJ2aWNlLmFkZChldmVudCwgeyBtdWx0aXBsZTogZmFsc2UsIGF1dG9IaWRlRHJvcEFyZWE6IHRydWUsIHN0eWxlOiAnY2FtZXJhJyB9KTtcbiAgICAgIGNvbnN0IGltZyA9IGZpcnN0QXJyYXlWYWx1ZShpbWFnZXMpO1xuICAgICAgaWYgKCFpbWc/LmRhdGFVcmwpIHJldHVybjtcbiAgICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmZvcm0uZ2V0KCdhdmF0YXInKTtcbiAgICAgIGlmIChjb250cm9sKSB7XG4gICAgICAgIGNvbnRyb2wuc2V0VmFsdWUoaW1nLmRhdGFVcmwpO1xuICAgICAgICBjb250cm9sLm1hcmtBc0RpcnR5KCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICAvLyBGYWxsYmFjayBpZiBjb250cm9sIG1pc3Npbmc6IHBhdGNoIHZhbHVlIGFuZCBtYXJrIGZvcm0gZGlydHlcbiAgICAgICAgdGhpcy5mb3JtLnBhdGNoVmFsdWUoeyBhdmF0YXI6IGltZy5kYXRhVXJsIH0pO1xuICAgICAgICB0aGlzLmZvcm0ubWFya0FzRGlydHkoKTtcbiAgICAgIH1cbiAgICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICBjb25zb2xlLmVycm9yKCdbYWNjb3VudF0gRXJyb3Igd2hpbGUgY2hhbmdpbmcgYXZhdGFyOicsIGVycj8ubWVzc2FnZSB8fCBlcnIpO1xuICAgIH1cbiAgfVxuXG4gIG5nT25EZXN0cm95KCkge1xuICAgIHN1cGVyLm5nT25EZXN0cm95KCk7XG4gICAgdGhpcy5zdG9wTGlzdGVuQ2hhbmdlcygpO1xuICAgIHRoaXMubmV0d29ya1N1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgfVxuXG4gIG9uTG9naW4oYWNjb3VudDogQWNjb3VudCkge1xuICAgIGNvbnNvbGUuZGVidWcoJ1thY2NvdW50XSBMb2dnZWQgYWNjb3VudDogJywgYWNjb3VudCk7XG4gICAgdGhpcy5pc0xvZ2luID0gdHJ1ZTtcblxuICAgIHRoaXMuc2V0VmFsdWUoYWNjb3VudCk7XG5cbiAgICB0aGlzLmVtYWlsLmNvbmZpcm1lZCA9IGFjY291bnQgJiYgYWNjb3VudC5lbWFpbCAmJiBhY2NvdW50LnN0YXR1c0lkICE9PSBTdGF0dXNJZHMuVEVNUE9SQVJZO1xuICAgIHRoaXMuZW1haWwubm90Q29uZmlybWVkID0gYWNjb3VudCAmJiBhY2NvdW50LmVtYWlsICYmICghYWNjb3VudC5zdGF0dXNJZCB8fCBhY2NvdW50LnN0YXR1c0lkID09PSBTdGF0dXNJZHMuVEVNUE9SQVJZKTtcblxuICAgIHRoaXMubmV0d29ya1N1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcbiAgICB0aGlzLm5ldHdvcmtTdWJzY3JpcHRpb24gPSBjb21iaW5lTGF0ZXN0KFtcbiAgICAgIHRoaXMuY29uZmlnU2VydmljZS5jb25maWcsXG4gICAgICB0aGlzLm5ldHdvcmsub25OZXR3b3JrU3RhdHVzQ2hhbmdlcy5waXBlKG1hcCgoY29ubmVjdGlvblR5cGUpID0+IGNvbm5lY3Rpb25UeXBlICE9PSAnbm9uZScpKSxcbiAgICBdKS5zdWJzY3JpYmUoKFtjb25maWcsIG9ubGluZV0pID0+IHtcbiAgICAgIHRoaXMub25Db25maWdMb2FkZWQoY29uZmlnKTtcblxuICAgICAgaWYgKG9ubGluZSkge1xuICAgICAgICB0aGlzLmVuYWJsZSgpO1xuICAgICAgICB0aGlzLm1hcmtBc1ByaXN0aW5lKCk7XG4gICAgICAgIHRoaXMuc3RhcnRMaXN0ZW5DaGFuZ2VzKCk7XG4gICAgICB9IGVsc2Uge1xuICAgICAgICB0aGlzLmRpc2FibGUoKTtcbiAgICAgICAgdGhpcy5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgICB0aGlzLnN0b3BMaXN0ZW5DaGFuZ2VzKCk7XG4gICAgICB9XG4gICAgICB0aGlzLm1hcmtBc0xvYWRlZCgpO1xuICAgIH0pO1xuXG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIG9uTG9nb3V0KCkge1xuICAgIHRoaXMuaXNMb2dpbiA9IGZhbHNlO1xuICAgIHRoaXMuZW1haWwuY29uZmlybWVkID0gZmFsc2U7XG4gICAgdGhpcy5lbWFpbC5ub3RDb25maXJtZWQgPSBmYWxzZTtcbiAgICB0aGlzLmVtYWlsLnNlbmRpbmcgPSBmYWxzZTtcbiAgICB0aGlzLmVtYWlsLmVycm9yID0gdW5kZWZpbmVkO1xuICAgIHRoaXMuZm9ybS5yZXNldCgpO1xuICAgIHRoaXMuZGlzYWJsZSgpO1xuXG4gICAgdGhpcy5uZXR3b3JrU3Vic2NyaXB0aW9uPy51bnN1YnNjcmliZSgpO1xuXG4gICAgdGhpcy5zdG9wTGlzdGVuQ2hhbmdlcygpO1xuXG4gICAgLy8gQmFjayB0byBob21lXG4gICAgdGhpcy5uYXZDb250cm9sbGVyLm5hdmlnYXRlUm9vdCgnLycpO1xuICB9XG5cbiAgYXN5bmMgc2V0VmFsdWUoZGF0YTogQWNjb3VudCwgb3B0cz86IHsgZW1pdEV2ZW50PzogYm9vbGVhbjsgb25seVNlbGY/OiBib29sZWFuIH0pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBzdXBlci5zZXRWYWx1ZShkYXRhLCBvcHRzKTtcblxuICAgIC8vIFNldCBvcHRpb25zXG4gICAgY29uc3QgeyBwcm9wZXJ0aWVzIH0gPSBkYXRhPy5zZXR0aW5ncz8uYXNMb2NhbFNldHRpbmdzKHsgZGVmaW5pdGlvbnM6IHRoaXMub3B0aW9uRGVmaW5pdGlvbnMgfSkgfHwge307XG4gICAgY29uc3QgcHJvcGVydGllc0VudGl0aWVzOiBQcm9wZXJ0eUVudGl0eVtdID0gdGhpcy5vcHRpb25EZWZpbml0aW9uc1xuICAgICAgLm1hcCgoZGVmaW5pdGlvbikgPT4ge1xuICAgICAgICBjb25zdCB2YWx1ZSA9IHByb3BlcnRpZXM/LltkZWZpbml0aW9uLmtleV07XG4gICAgICAgIHJldHVybiBpc05vdE5pbCh2YWx1ZSkgPyBQcm9wZXJ0eUVudGl0eS5mcm9tT2JqZWN0KHsgZGVmaW5pdGlvbiwgdmFsdWUgfSkgOiBudWxsO1xuICAgICAgfSlcbiAgICAgIC5maWx0ZXIoaXNOb3ROaWwpO1xuXG4gICAgaWYgKHRoaXMucHJvcGVydGllc1RhYmxlKSB7XG4gICAgICBhd2FpdCB0aGlzLnByb3BlcnRpZXNUYWJsZS5yZWFkeSgpO1xuICAgICAgdGhpcy5wcm9wZXJ0aWVzVGFibGUudmFsdWUgPSBwcm9wZXJ0aWVzRW50aXRpZXM7XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudG9rZW5zVGFibGUpIHtcbiAgICAgIGF3YWl0IHRoaXMudG9rZW5zVGFibGUucmVhZHkoKTtcbiAgICAgIHRoaXMudG9rZW5zVGFibGUudmFsdWUgPSBkYXRhLnRva2VucztcbiAgICB9XG4gIH1cblxuICBhc3luYyByZWZyZXNoKF8/OiBFdmVudCkge1xuICAgIHRoaXMuZGlzYWJsZSgpO1xuICAgIHRoaXMubWFya0FzTG9hZGluZygpO1xuXG4gICAgcmV0dXJuIHRoaXMuYWNjb3VudFNlcnZpY2UucmVsb2FkKCk7XG4gIH1cblxuICBzdGFydExpc3RlbkNoYW5nZXMoKSB7XG4gICAgaWYgKHRoaXMuY2hhbmdlc1N1YnNjcmlwdGlvbikgcmV0dXJuOyAvLyBhbHJlYWR5IHN0YXJ0ZWRcbiAgICB0aGlzLmNoYW5nZXNTdWJzY3JpcHRpb24gPSB0aGlzLmFjY291bnRTZXJ2aWNlLmxpc3RlbkNoYW5nZXMoKTtcbiAgfVxuXG4gIHN0b3BMaXN0ZW5DaGFuZ2VzKCkge1xuICAgIGlmICghdGhpcy5jaGFuZ2VzU3Vic2NyaXB0aW9uKSByZXR1cm47XG4gICAgdGhpcy5jaGFuZ2VzU3Vic2NyaXB0aW9uLnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5jaGFuZ2VzU3Vic2NyaXB0aW9uID0gdW5kZWZpbmVkO1xuICB9XG5cbiAgYXN5bmMgc2VuZENvbmZpcm1hdGlvbkVtYWlsKGV2ZW50OiBNb3VzZUV2ZW50KSB7XG4gICAgY29uc3QganNvbiA9IHRoaXMuZm9ybS52YWx1ZTtcbiAgICBqc29uLmVtYWlsID0gdGhpcy5mb3JtLmNvbnRyb2xzWydlbWFpbCddLnZhbHVlO1xuICAgIGlmICghanNvbi5lbWFpbCB8fCAhdGhpcy5lbWFpbC5ub3RDb25maXJtZWQpIHtcbiAgICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgICByZXR1cm4gZmFsc2U7XG4gICAgfVxuXG4gICAgdGhpcy5lbWFpbC5zZW5kaW5nID0gdHJ1ZTtcbiAgICBjb25zb2xlLmRlYnVnKCdbYWNjb3VudF0gU2VuZGluZyBjb25maXJtYXRpb24gZW1haWwuLi4nKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5hY2NvdW50U2VydmljZS5zZW5kQ29uZmlybWF0aW9uRW1haWwoanNvbi5lbWFpbCwgKGpzb24uc2V0dGluZ3MgJiYganNvbi5zZXR0aW5ncy5sb2NhbGUpIHx8IHRoaXMudHJhbnNsYXRlLmN1cnJlbnRMYW5nKTtcbiAgICAgIGNvbnNvbGUuZGVidWcoJ1thY2NvdW50XSBDb25maXJtYXRpb24gZW1haWwgc2VudC4nKTtcbiAgICAgIHRoaXMuZW1haWwuc2VuZGluZyA9IGZhbHNlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgdGhpcy5lbWFpbC5zZW5kaW5nID0gZmFsc2U7XG4gICAgICB0aGlzLmVtYWlsLmVycm9yID0gKGVyciAmJiBlcnIubWVzc2FnZSkgfHwgZXJyO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIHNhdmUoZXZlbnQ/OiBFdmVudCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIGlmICh0aGlzLnNhdmluZykgcmV0dXJuIGZhbHNlO1xuXG4gICAgaWYgKCF0aGlzLmZvcm0udmFsaWQpIHtcbiAgICAgIGF3YWl0IEFwcEZvcm1VdGlscy53YWl0V2hpbGVQZW5kaW5nKHRoaXMuZm9ybSk7XG5cbiAgICAgIGlmICh0aGlzLmZvcm0uaW52YWxpZCkge1xuICAgICAgICBBcHBGb3JtVXRpbHMubG9nRm9ybUVycm9ycyh0aGlzLmZvcm0pO1xuICAgICAgICB0aGlzLmZvcm0ubWFya0FsbEFzVG91Y2hlZCgpO1xuICAgICAgICByZXR1cm4gZmFsc2U7XG4gICAgICB9XG4gICAgfVxuXG4gICAgdGhpcy5zdWJtaXR0ZWQgPSB0cnVlO1xuICAgIHRoaXMuc2F2aW5nID0gdHJ1ZTtcbiAgICB0aGlzLmVycm9yID0gdW5kZWZpbmVkO1xuXG4gICAgY29uc3QgbmV3QWNjb3VudCA9IEFjY291bnQuZnJvbU9iamVjdCh7XG4gICAgICAuLi50aGlzLmFjY291bnRTZXJ2aWNlLmFjY291bnQuYXNPYmplY3QoKSxcbiAgICAgIC4uLnRoaXMuZm9ybS52YWx1ZSxcbiAgICB9KTtcblxuICAgIGlmIChpc05vdEVtcHR5QXJyYXkodGhpcy5vcHRpb25EZWZpbml0aW9ucykgJiYgdGhpcy5wcm9wZXJ0aWVzVGFibGUpIHtcbiAgICAgIC8vIE1lcmdlIHByb3BlcnRpZXNcbiAgICAgIGF3YWl0IHRoaXMucHJvcGVydGllc1RhYmxlLnNhdmUoKTtcbiAgICAgIGNvbnN0IHByb3BlcnR5RW50aXRpZXMgPSB0aGlzLnByb3BlcnRpZXNUYWJsZS52YWx1ZSB8fCBbXTtcbiAgICAgIGNvbnN0IHByb3BlcnRpZXM6IFByb3BlcnR5TWFwID0gcHJvcGVydHlFbnRpdGllcy5yZWR1Y2UoKHJlcywgaXRlbSkgPT4ge1xuICAgICAgICByZXNbaXRlbS5pZF0gPSBpdGVtLnZhbHVlO1xuICAgICAgICByZXR1cm4gcmVzO1xuICAgICAgfSwge30pO1xuICAgICAgY29uc3QgbmV3UHJvcGVydGllcyA9IHsgLi4ubmV3QWNjb3VudC5zZXR0aW5ncy5jb250ZW50Wydwcm9wZXJ0aWVzJ10sIC4uLnByb3BlcnRpZXMgfTtcbiAgICAgIG5ld0FjY291bnQuc2V0dGluZ3MubWVyZ2UoPExvY2FsU2V0dGluZ3M+eyBwcm9wZXJ0aWVzOiBuZXdQcm9wZXJ0aWVzIH0sIFsncHJvcGVydGllcyddKTtcbiAgICB9IGVsc2UgaWYgKG5ld0FjY291bnQuc2V0dGluZ3MuY29udGVudFsncHJvcGVydGllcyddKSB7XG4gICAgICAvLyBDbGVhbiBwcm9wZXJ0aWVzXG4gICAgICBkZWxldGUgbmV3QWNjb3VudC5zZXR0aW5ncy5jb250ZW50Wydwcm9wZXJ0aWVzJ107XG4gICAgfVxuXG4gICAgaWYgKHRoaXMudG9rZW5zVGFibGUpIHtcbiAgICAgIGF3YWl0IHRoaXMudG9rZW5zVGFibGUuc2F2ZSgpO1xuICAgICAgbmV3QWNjb3VudC50b2tlbnMgPSB0aGlzLnRva2Vuc1RhYmxlLnZhbHVlO1xuICAgIH1cblxuICAgIGNvbnNvbGUuZGVidWcoJ1thY2NvdW50XSBTYXZpbmcgYWNjb3VudC4uLicsIG5ld0FjY291bnQpO1xuICAgIHRyeSB7XG4gICAgICB0aGlzLmRpc2FibGUoKTtcblxuICAgICAgYXdhaXQgdGhpcy5hY2NvdW50U2VydmljZS5zYXZlKG5ld0FjY291bnQpO1xuXG4gICAgICAvLyBSZWxvYWRcbiAgICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy5vbkxvZ2luKHRoaXMuYWNjb3VudFNlcnZpY2UuYWNjb3VudCksIDEwMCk7XG5cbiAgICAgIHRoaXMubWFya0FzUHJpc3RpbmUoKTtcbiAgICAgIHJldHVybiB0cnVlO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcihlcnIpO1xuICAgICAgdGhpcy5lcnJvciA9IChlcnIgJiYgZXJyLm1lc3NhZ2UpIHx8IGVycjtcbiAgICAgIHJldHVybiBmYWxzZTtcbiAgICB9IGZpbmFsbHkge1xuICAgICAgdGhpcy5zYXZpbmcgPSBmYWxzZTtcbiAgICAgIHRoaXMuZW5hYmxlKCk7XG4gICAgfVxuICB9XG5cbiAgZW5hYmxlKG9wdHM/OiB7IG9ubHlTZWxmPzogYm9vbGVhbjsgZW1pdEV2ZW50PzogYm9vbGVhbiB9KSB7XG4gICAgc3VwZXIuZW5hYmxlKG9wdHMpO1xuXG4gICAgLy8gU29tZSBmaWVsZHMgYXJlIGFsd2F5cyBkaXNhYmxlXG4gICAgdGhpcy5mb3JtLmNvbnRyb2xzLmVtYWlsLmRpc2FibGUoKTtcbiAgICB0aGlzLmZvcm0uY29udHJvbHMubWFpblByb2ZpbGUuZGlzYWJsZSgpO1xuICAgIHRoaXMuZm9ybS5jb250cm9scy5wdWJrZXkuZGlzYWJsZSgpO1xuXG4gICAgLy8gRGlzYWJsZSBhY2NvdW50IGZpZWxkcyBpZiByZWFkb25seSBieSBjb25maWd1cmF0aW9uXG4gICAgY29uc3QgZGlzYWJsZWQgPSB0aGlzLmFjY291bnRSZWFkT25seTtcbiAgICBpZiAoZGlzYWJsZWQpIHtcbiAgICAgIHRoaXMuZm9ybS5jb250cm9scy5sYXN0TmFtZS5kaXNhYmxlKCk7XG4gICAgICB0aGlzLmZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpc2FibGUoKTtcbiAgICB9XG5cbiAgICAvLyBBbHdheXMgZGlzYWJsZSBzb21lIGFkZGl0aW9uYWwgZmllbGRzXG4gICAgdGhpcy5hZGRpdGlvbmFsRmllbGRzLmZvckVhY2goKGZpZWxkKSA9PiB7XG4gICAgICBjb25zdCBjb250cm9sID0gdGhpcy5mb3JtLmNvbnRyb2xzW2ZpZWxkLmtleV07XG4gICAgICBpZiAoIWNvbnRyb2wpIHJldHVybjsgLy8gU2tpcFxuXG4gICAgICBjb25zdCBmaWVsZERpc2FibGVkID0gZGlzYWJsZWQgfHwgZmllbGQuZXh0cmE/LmFjY291bnQ/LmRpc2FibGVkIHx8IGZhbHNlO1xuICAgICAgaWYgKGZpZWxkRGlzYWJsZWQgJiYgY29udHJvbC5lbmFibGVkKSB7XG4gICAgICAgIGNvbnRyb2wuZGlzYWJsZSgpO1xuICAgICAgfVxuICAgICAgY29uc3QgcmVxdWlyZWQgPSBmaWVsZC5leHRyYT8uYWNjb3VudD8ucmVxdWlyZWQgPz8gZmFsc2U7XG4gICAgICBpZiAoIWZpZWxkLnJlcXVpcmVkICYmIHJlcXVpcmVkKSB7XG4gICAgICAgIGNvbnRyb2wuc2V0VmFsaWRhdG9ycyhjb250cm9sLnZhbGlkYXRvciA/IFZhbGlkYXRvcnMuY29tcG9zZShbY29udHJvbC52YWxpZGF0b3IsIFZhbGlkYXRvcnMucmVxdWlyZWRdKSA6IFZhbGlkYXRvcnMucmVxdWlyZWQpO1xuICAgICAgfVxuICAgIH0pO1xuICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBhc3luYyBjYW5jZWwoKSB7XG4gICAgYXdhaXQgc3VwZXIuY2FuY2VsKCk7XG4gIH1cblxuICBhc3luYyBjbG9zZShfPzogRXZlbnQpIHtcbiAgICBpZiAodGhpcy5zYXZpbmcpIHJldHVybjtcblxuICAgIC8vIEJhY2sgdG8gaG9tZVxuICAgIHJldHVybiB0aGlzLm5hdkNvbnRyb2xsZXIubmF2aWdhdGVSb290KCcvJyk7IC8vIGJhY2sgdG8gaG9tZVxuICB9XG5cbiAgQEhvc3RMaXN0ZW5lcignd2luZG93OmJlZm9yZXVubG9hZCcsIFsnJGV2ZW50J10pXG4gIGhhbmRsZVJlZnJlc2goZXZlbnQ6IEJlZm9yZVVubG9hZEV2ZW50KTogdm9pZCB7XG4gICAgLy8gQXZvaWQgdG8gcXVpdCB3ZWIgYnJvd3NlciBwYWdlLCB3aXRob3V0IHNhdmluZ1xuICAgIGlmICghdGhpcy5tb2JpbGUgJiYgdGhpcy5kaXJ0eSkge1xuICAgICAgZXZlbnQucHJldmVudERlZmF1bHQoKTsgLy8gQXZvaWQgdG8gcXVpdCB3aXRob3V0IHNhdmluZ1xuICAgIH1cbiAgfVxuXG4gIHByb3RlY3RlZCBvbkNvbmZpZ0xvYWRlZChjb25maWc6IENvbmZpZ3VyYXRpb24pIHtcbiAgICBjb25zb2xlLmRlYnVnKCdbYWNjb3VudF0gQ29uZmlnIGxvYWRlZDogJywgY29uZmlnKTtcbiAgICB0aGlzLmFjY291bnRSZWFkT25seSA9IGNvbmZpZy5nZXRQcm9wZXJ0eUFzQm9vbGVhbihDT1JFX0NPTkZJR19PUFRJT05TLkFDQ09VTlRfUkVBRE9OTFkpO1xuICAgIHRoaXMuc2hvd0xhdExvbkZvcm1hdCA9XG4gICAgICBjb25maWcuZ2V0UHJvcGVydHlBc0Jvb2xlYW4oQ09SRV9DT05GSUdfT1BUSU9OUy5BQ0NPVU5UX0xBVF9MT05HX0ZPUk1BVF9FTkFCTEUpICYmXG4gICAgICAvLyBGb3IgY29tcGF0aWJpbGl0eSB3aXRoIGRlcHJlY2F0ZWQga2V5XG4gICAgICBjb25maWcuZ2V0UHJvcGVydHlBc0Jvb2xlYW4oQ09SRV9DT05GSUdfT1BUSU9OUy5ERUZBVUxUX0xBVF9MT05HX0ZPUk1BVF9FTkFCTEVEKTtcbiAgICB0aGlzLnNob3dBdmF0YXIgPSBjb25maWcuZ2V0UHJvcGVydHlBc0Jvb2xlYW4oQ09SRV9DT05GSUdfT1BUSU9OUy5BQ0NPVU5UX0FWQVRBUl9FTkFCTEUpO1xuXG4gICAgY29uc3QgYXV0aFRva2VuVHlwZSA9IGNvbmZpZy5nZXRQcm9wZXJ0eShDT1JFX0NPTkZJR19PUFRJT05TLkFVVEhfVE9LRU5fVFlQRSkgYXMgQXV0aFRva2VuVHlwZTtcbiAgICB0aGlzLmNhbkNoYW5nZVBhc3N3b3JkID0gYXV0aFRva2VuVHlwZSA9PT0gJ3Rva2VuJztcbiAgICB0aGlzLnNob3dTZWN1cml0eURldGFpbHMgPSB0aGlzLmNhbkNoYW5nZVBhc3N3b3JkO1xuICAgIHRoaXMuc2hvd0FwaVRva2VucyA9IGNvbmZpZy5nZXRQcm9wZXJ0eUFzQm9vbGVhbihDT1JFX0NPTkZJR19PUFRJT05TLkFVVEhfQVBJX1RPS0VOX0VOQUJMRUQpO1xuICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFya0ZvckNoZWNrKCkge1xuICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgb3BlbkNoYW5nZVBhc3N3b3JkUGFnZSgpIHtcbiAgICB0aGlzLm5hdkNvbnRyb2xsZXIubmF2aWdhdGVGb3J3YXJkKCdhY2NvdW50L3Bhc3N3b3JkJyk7XG4gIH1cbn1cbiIsIjxhcHAtdG9vbGJhclxuICBbdGl0bGVdPVwiJ0FDQ09VTlQuVElUTEUnIHwgdHJhbnNsYXRlXCJcbiAgY29sb3I9XCJwcmltYXJ5XCJcbiAgW2hhc1ZhbGlkYXRlXT1cImRpcnR5ICYmICFzYXZpbmdcIlxuICBbaGFzQ2xvc2VdPVwiIWRpcnR5ICYmICFzYXZpbmdcIlxuICAob25WYWxpZGF0ZSk9XCJzYXZlKClcIlxuICAob25DbG9zZSk9XCJjbG9zZSgkZXZlbnQpXCJcbj5cbiAgPGlvbi1idXR0b25zIHNsb3Q9XCJlbmRcIj5cbiAgICBAaWYgKGxvYWRpbmcgfHwgc2F2aW5nKSB7XG4gICAgICA8IS0tIGxvYWRlciAtLT5cbiAgICAgIDxpb24tc3Bpbm5lcj48L2lvbi1zcGlubmVyPlxuICAgIH0gQGVsc2UgaWYgKG5ldHdvcmsub25saW5lKSB7XG4gICAgICA8IS0tIHJlZnJlc2ggYnV0dG9uIChpZiBvbmxpbmUpIC0tPlxuICAgICAgPGlvbi1idXR0b24gW21hdFRvb2x0aXBdPVwiJ0NPTU1PTi5CVE5fUkVGUkVTSCcgfCB0cmFuc2xhdGVcIiAoY2xpY2spPVwicmVmcmVzaCgkZXZlbnQpXCI+XG4gICAgICAgIDxtYXQtaWNvbiBzbG90PVwiaWNvbi1vbmx5XCI+cmVmcmVzaDwvbWF0LWljb24+XG4gICAgICA8L2lvbi1idXR0b24+XG4gICAgfVxuICA8L2lvbi1idXR0b25zPlxuPC9hcHAtdG9vbGJhcj5cblxuPGlvbi1jb250ZW50PlxuICA8IS0tIEluc3RhbGwgKGFuZCB1cGdyYWRlKSBjYXJkIC0tPlxuICA8YXBwLWluc3RhbGwtdXBncmFkZS1jYXJkIFtpc0xvZ2luXT1cImlzTG9naW5cIiBbc2hvd0luc3RhbGxCdXR0b25dPVwidHJ1ZVwiPjwvYXBwLWluc3RhbGwtdXBncmFkZS1jYXJkPlxuXG4gIDwhLS0gZXJyb3IgLS0+XG4gIEBpZiAobW9iaWxlICYmIChlcnJvclN1YmplY3QgfCBhc3luYyk7IGFzIGVycm9yKSB7XG4gICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiPlxuICAgICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgY2xhc3M9XCJlcnJvclwiIFtpbm5lckhUTUxdPVwiZXJyb3IgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgICA8L2lvbi1pdGVtPlxuICB9XG5cbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCIgbm92YWxpZGF0ZSBjbGFzcz1cImZvcm0tY29udGFpbmVyXCI+XG4gICAgPG1hdC10YWItZ3JvdXBcbiAgICAgICN0YWJHcm91cFxuICAgICAgWyhzZWxlY3RlZEluZGV4KV09XCJzZWxlY3RlZFRhYkluZGV4XCJcbiAgICAgIGNsYXNzPVwibWF0LW1kYy10YWItZGlzYWJsZWQtaGlkZGVuXCJcbiAgICAgIFttYXQtc3RyZXRjaC10YWJzXT1cIm1vYmlsZVwiXG4gICAgICBkeW5hbWljSGVpZ2h0XG4gICAgPlxuICAgICAgPCEtLSBUQUI6IHVzZXIgZGV0YWlscyAtLT5cbiAgICAgIDxtYXQtdGFiIFtsYWJlbF09XCInQUNDT1VOVC5VU0VSX0RFVEFJTFMuVElUTEUnIHwgdHJhbnNsYXRlXCIgY2xhc3M9XCJpb24tcGFkZGluZ1wiPlxuICAgICAgICA8bmctdGVtcGxhdGUgbWF0LXRhYi1sYWJlbD5cbiAgICAgICAgICA8bWF0LWljb24+XG4gICAgICAgICAgICA8aW9uLWljb24gbWF0UHJlZml4IHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJwZXJzb24tY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICAgICAgICA8L21hdC1pY29uPlxuICAgICAgICAgIDxpb24tbGFiZWw+e3sgJ0FDQ09VTlQuVVNFUl9ERVRBSUxTLlRJVExFJyB8IHRyYW5zbGF0ZSB9fTwvaW9uLWxhYmVsPlxuICAgICAgICAgIDxpb24taWNvbiBzbG90PVwiZW5kXCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiIGNvbG9yPVwiZGFuZ2VyXCIgKm5nSWY9XCJzdWJtaXR0ZWQgJiYgZm9ybS5pbnZhbGlkXCI+PC9pb24taWNvbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPGlvbi1ncmlkIGNsYXNzPVwiaW9uLW5vLXBhZGRpbmdcIj5cbiAgICAgICAgICA8aW9uLXJvdz5cbiAgICAgICAgICAgIDwhLS0gbGVmdCAgbWFyZ2luIC0tPlxuICAgICAgICAgICAgPGlvbi1jb2wgc2l6ZT1cIjBcIiBzaXplLWxnPVwiMVwiIHNpemUteGw9XCIyXCI+Jm5ic3A7PC9pb24tY29sPlxuXG4gICAgICAgICAgICA8aW9uLWNvbCBjbGFzcz1cImlvbi1wYWRkaW5nXCI+XG4gICAgICAgICAgICAgIDwhLS0gQXZhdGFyIGJsb2NrIC0tPlxuICAgICAgICAgICAgICBAaWYgKHNob3dBdmF0YXIpIHtcbiAgICAgICAgICAgICAgICBAbGV0IGFjY291bnRBdmF0YXIgPSBmb3JtPy5jb250cm9scz8uYXZhdGFyPy52YWx1ZSB8fCBmb3JtPy52YWx1ZT8uYXZhdGFyIHx8IGFjY291bnRTZXJ2aWNlPy5hY2NvdW50Py5hdmF0YXIgfHwgZGVmYXVsdEF2YXRhckltYWdlO1xuICAgICAgICAgICAgICAgIEBsZXQgaXNEZWZhdWx0QXZhdGFyID0gYWNjb3VudEF2YXRhcj8uZW5kc1dpdGgoZGVmYXVsdEF2YXRhckltYWdlKTtcbiAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCIgY2xhc3M9XCJpb24tbWFyZ2luLWJvdHRvbVwiIHN0eWxlPVwiLS1pbm5lci1wYWRkaW5nLWVuZDogMFwiPlxuICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gc2xvdD1cInN0YXJ0XCIgZmlsbD1cImNsZWFyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidXNlci1hdmF0YXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLmJhY2tncm91bmQtaW1hZ2VdPVwiJ3VybCgnICsgKGFjY291bnRBdmF0YXIgfHwgZGVmYXVsdEF2YXRhckltYWdlKSArICcpJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25DaGFuZ2VBdmF0YXIoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbbWF0VG9vbHRpcF09XCInSU1BR0UuQlROX0NBTUVSQV9TT1VSQ0UnIHwgdHJhbnNsYXRlXCJcbiAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgQGlmICghYWNjb3VudFJlYWRPbmx5KSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIFtjbGFzcy52aXNpYmxlLWhvdmVyXT1cIiFpc0RlZmF1bHRBdmF0YXJcIiBuYW1lPVwiY2FtZXJhXCIgc2xvdD1cImljb24tb25seVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgPGlvbi1saXN0LWhlYWRlcj48cCBbaW5uZXJIVE1MXT1cIidBQ0NPVU5ULlVTRVJfREVUQUlMUy5ERVNDUklQVElPTicgfCB0cmFuc2xhdGVcIj48L3A+PC9pb24tbGlzdC1oZWFkZXI+XG5cbiAgICAgICAgICAgICAgPGlvbi1saXN0IFtpbnNldF09XCJtb2JpbGVcIj5cbiAgICAgICAgICAgICAgICA8IS0tIEVtYWlsIC0tPlxuICAgICAgICAgICAgICAgIDxpb24taXRlbSBsaW5lcz1cIm5vbmVcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5FTUFJTCcgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IGZvcm1Db250cm9sTmFtZT1cImVtYWlsXCIgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1yZWQgZW1haWxcIiAvPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5lbWFpbC5oYXNFcnJvcigncmVxdWlyZWQnKSAmJiBmb3JtLmNvbnRyb2xzLmVtYWlsLmRpcnR5XCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5lbWFpbC5oYXNFcnJvcignZW1haWwnKSAmJiBmb3JtLmNvbnRyb2xzLmVtYWlsLmRpcnR5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX05PVF9WQUxJRF9FTUFJTCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuXG4gICAgICAgICAgICAgICAgQGlmIChlbWFpbD8ubm90Q29uZmlybWVkKSB7XG4gICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxpb24tZ3JpZCBjbGFzcz1cImlvbi1uby1wYWRkaW5nIGlvbi1wYWRkaW5nLWJvdHRvbVwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxpb24tcm93PlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1jb2wgY29sb3I9XCJkYW5nZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIHNsb3Q9XCJzdGFydFwiIGNvbG9yPVwiZGFuZ2VyXCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxpb24tdGV4dCBbaW5uZXJIVE1MXT1cIidBQ0NPVU5ULkVNQUlMX05PVF9DT05GSVJNRURfTEFCRUwnIHwgdHJhbnNsYXRlXCI+PC9pb24tdGV4dD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1yb3c+XG5cbiAgICAgICAgICAgICAgICAgICAgICA8aW9uLXJvdyBzdHlsZT1cImhlaWdodDogNTFweFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1jb2wgc3R5bGU9XCJ0ZXh0LWFsaWduOiByaWdodFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLXRleHQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNtYWxsIFtpbm5lckhUTUxdPVwiJ0FDQ09VTlQuRU1BSUxfTk9UX1JFQ0VJVkVEX1FVRVNUSU9OJyB8IHRyYW5zbGF0ZVwiPjwvc21hbGw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLXRleHQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1jb2w+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWNvbCBzaXplPVwiYXV0b1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKCFlbWFpbC5zZW5kaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gZmlsbD1cInNvbGlkXCIgY29sb3I9XCJzZWNvbmRhcnlcIiAoY2xpY2spPVwic2VuZENvbmZpcm1hdGlvbkVtYWlsKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ICdBQ0NPVU5ULkJUTl9SRVNFTkQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLXNwaW5uZXIgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiPjwvaW9uLXNwaW5uZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1yb3c+XG5cbiAgICAgICAgICAgICAgICAgICAgICA8aW9uLXJvdyAqbmdJZj1cImVtYWlsLmVycm9yICYmICFlbWFpbC5zZW5kaW5nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWNvbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJlbWFpbC5lcnJvciAmJiAhZW1haWwuc2VuZGluZ1wiIFtpbm5lckhUTUxdPVwiZW1haWwuZXJyb3IgfCB0cmFuc2xhdGVcIj48L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1jb2w+XG4gICAgICAgICAgICAgICAgICAgICAgPC9pb24tcm93PlxuICAgICAgICAgICAgICAgICAgICA8L2lvbi1ncmlkPlxuICAgICAgICAgICAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPCEtLSBMYXN0IG5hbWUgLS0+XG4gICAgICAgICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdVU0VSLkxBU1RfTkFNRScgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICBbYXBwQXV0b2ZvY3VzXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgIFthdXRvZm9jdXNEZWxheV09XCI1MDBcIlxuICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImxhc3ROYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJzZWN0aW9uLWJsdWUgZmFtaWx5LW5hbWVcIlxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImZvcm0uY29udHJvbHMubGFzdE5hbWUuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgZm9ybS5jb250cm9scy5sYXN0TmFtZS5kaXJ0eVwiXG4gICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImZvcm0uY29udHJvbHMubGFzdE5hbWUuaGFzRXJyb3IoJ21pbmxlbmd0aCcpICYmIGZvcm0uY29udHJvbHMubGFzdE5hbWUuZGlydHlcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj57eyAnRVJST1IuRklFTERfTUlOX0xFTkdUSCcgfCB0cmFuc2xhdGU6IHsgcmVxdWlyZWRMZW5ndGg6IDIgfSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG5cbiAgICAgICAgICAgICAgICA8IS0tIEZpcnN0IG5hbWUgLS0+XG4gICAgICAgICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdVU0VSLkZJUlNUX05BTUUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJmaXJzdE5hbWVcIiBhdXRvY29tcGxldGU9XCJzZWN0aW9uLWJsdWUgZ2l2ZW4tbmFtZVwiIHJlcXVpcmVkIC8+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCJcbiAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ21pbmxlbmd0aCcpICYmIGZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7IHJlcXVpcmVkTGVuZ3RoOiAyIH0gfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuXG4gICAgICAgICAgICAgICAgPCEtLSBBZGRpdGlvbmFsIGZpZWxkcyAtLT5cbiAgICAgICAgICAgICAgICBAZm9yIChkZWZpbml0aW9uIG9mIGFkZGl0aW9uYWxGaWVsZHM7IHRyYWNrIGRlZmluaXRpb24ua2V5KSB7XG4gICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxhcHAtZm9ybS1maWVsZFxuICAgICAgICAgICAgICAgICAgICAgIFtkZWZpbml0aW9uXT1cImRlZmluaXRpb25cIlxuICAgICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbE5hbWVdPVwiZGVmaW5pdGlvbi5rZXlcIlxuICAgICAgICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChkZWZpbml0aW9uLmV4dHJhICYmIGRlZmluaXRpb24uZXh0cmEuYWNjb3VudCAmJiBkZWZpbml0aW9uLmV4dHJhLmFjY291bnQucmVxdWlyZWQpIHx8IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgPjwvYXBwLWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9pb24tbGlzdD5cblxuICAgICAgICAgICAgICA8IS0tIFNlY3VyaXR5IC0tPlxuICAgICAgICAgICAgICBAaWYgKHNob3dTZWN1cml0eURldGFpbHMpIHtcbiAgICAgICAgICAgICAgICA8aW9uLWxpc3QtaGVhZGVyPjxoMyB0cmFuc2xhdGU+QUNDT1VOVC5TRUNVUklUWS5USVRMRTwvaDM+PC9pb24tbGlzdC1oZWFkZXI+XG5cbiAgICAgICAgICAgICAgICA8aW9uLWxpc3QgW2luc2V0XT1cIm1vYmlsZVwiPlxuICAgICAgICAgICAgICAgICAgPGlvbi1pdGVtXG4gICAgICAgICAgICAgICAgICAgIFtidXR0b25dPVwibW9iaWxlXCJcbiAgICAgICAgICAgICAgICAgICAgcm91dGVyRGlyZWN0aW9uPVwiZm9yd2FyZFwiXG4gICAgICAgICAgICAgICAgICAgIGxpbmVzPVwibm9uZVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvcGVuQ2hhbmdlUGFzc3dvcmRQYWdlKClcIlxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICBAaWYgKCFtb2JpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8aW9uLWljb24gc2xvdD1cInN0YXJ0XCIgbmFtZT1cImtleXBhZFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgPGlvbi1sYWJlbD57eyAnQUNDT1VOVC5TRUNVUklUWS5QQVNTV09SRCcgfCB0cmFuc2xhdGUgfX08L2lvbi1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA8aW9uLXRleHQgY29sb3I9XCJ0ZXJ0aWFyeVwiPnt7ICdBQ0NPVU5ULlNFQ1VSSVRZLkJUTl9DSEFOR0VfUEFTU1dPUkQnIHwgdHJhbnNsYXRlIH19PC9pb24tdGV4dD5cbiAgICAgICAgICAgICAgICAgICAgQGlmICghbW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIHNsb3Q9XCJlbmRcIiBjb2xvcj1cInRlcnRpYXJ5XCIgbmFtZT1cImNoZXZyb24tZm9yd2FyZFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgICAgICAgPC9pb24tbGlzdD5cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIDwhLS0gVGVjaG5pY2FsIGRldGFpbHMgLS0+XG4gICAgICAgICAgICAgIEBpZiAoc2hvd1RlY2huaWNhbERldGFpbHMpIHtcbiAgICAgICAgICAgICAgICA8aW9uLWxpc3QtaGVhZGVyPjxoMyB0cmFuc2xhdGU+QUNDT1VOVC5VU0VSX0RFVEFJTFMuVEVDSE5JQ0FMX0RJVklERVI8L2gzPjwvaW9uLWxpc3QtaGVhZGVyPlxuXG4gICAgICAgICAgICAgICAgPGlvbi1saXN0IFtpbnNldF09XCJtb2JpbGVcIj5cbiAgICAgICAgICAgICAgICAgIDwhLS0gcHJvZmlsZSAtLT5cbiAgICAgICAgICAgICAgICAgIDxpb24taXRlbSBsaW5lcz1cIm5vbmVcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ0FDQ09VTlQuVVNFUl9ERVRBSUxTLlBST0ZJTEUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IGhpZGRlbiByZWFkb25seT1cInRydWVcIiBmb3JtQ29udHJvbE5hbWU9XCJtYWluUHJvZmlsZVwiIHJlcXVpcmVkIC8+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgJ1VTRVIuUFJPRklMRV9FTlVNLicgKyBmb3JtLmNvbnRyb2xzLm1haW5Qcm9maWxlLnZhbHVlIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiZm9ybS5jb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ21haW5Qcm9maWxlJykgJiYgZm9ybS5jb250cm9scy5tYWluUHJvZmlsZS5kaXJ0eVwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPC9pb24taXRlbT5cblxuICAgICAgICAgICAgICAgICAgPCEtLSBwdWJrZXkgLS0+XG4gICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdBQ0NPVU5ULlVTRVJfREVUQUlMUy5QVUJLRVknIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IHJlYWRvbmx5PVwidHJ1ZVwiIGZvcm1Db250cm9sTmFtZT1cInB1YmtleVwiIHJlcXVpcmVkIC8+XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJmb3JtLmNvbnRyb2xzLmZpcnN0TmFtZS5oYXNFcnJvcigncHVia2V5JykgJiYgZm9ybS5jb250cm9scy5maXJzdE5hbWUuZGlydHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ3B1YmtleScpICYmIGZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+RVJST1IuRklFTERfTk9UX1ZBTElEX1BVQktFWTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgICAgICAgPC9pb24tbGlzdD5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9pb24tY29sPlxuXG4gICAgICAgICAgICA8IS0tIHJpZ2h0IG1hcmdpbiAtLT5cbiAgICAgICAgICAgIDxpb24tY29sIHNpemU9XCIwXCIgc2l6ZS1sZz1cIjFcIiBzaXplLXhsPVwiMlwiPiZuYnNwOzwvaW9uLWNvbD5cbiAgICAgICAgICA8L2lvbi1yb3c+XG4gICAgICAgIDwvaW9uLWdyaWQ+XG4gICAgICA8L21hdC10YWI+XG5cbiAgICAgIDwhLS0gVEFCOiBzZXR0aW5ncyAtLT5cbiAgICAgIDxtYXQtdGFiIFtsYWJlbF09XCInQUNDT1VOVC5TRVRUSU5HUy5USVRMRScgfCB0cmFuc2xhdGVcIiBmb3JtR3JvdXBOYW1lPVwic2V0dGluZ3NcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIG1hdC10YWItbGFiZWw+XG4gICAgICAgICAgPG1hdC1pY29uPlxuICAgICAgICAgICAgPGlvbi1pY29uIG1hdFByZWZpeCBzbG90PVwic3RhcnRcIiBuYW1lPVwic2V0dGluZ3NcIj48L2lvbi1pY29uPlxuICAgICAgICAgIDwvbWF0LWljb24+XG4gICAgICAgICAgPGlvbi1sYWJlbCB0cmFuc2xhdGU+QUNDT1VOVC5TRVRUSU5HUy5USVRMRTwvaW9uLWxhYmVsPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpb24tcGFkZGluZ1wiPlxuICAgICAgICAgIDxwIFtpbm5lckhUTUxdPVwiJ0FDQ09VTlQuU0VUVElOR1MuREVTQ1JJUFRJT04nIHwgdHJhbnNsYXRlXCI+PC9wPlxuXG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnQUNDT1VOVC5TRVRUSU5HUy5MT0NBTEUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJsb2NhbGVcIiByZXF1aXJlZD5cbiAgICAgICAgICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgbG9jYWxlc1wiIFt2YWx1ZV09XCJpdGVtLmtleVwiPlxuICAgICAgICAgICAgICAgIHt7IGl0ZW0udmFsdWUgfX1cbiAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPG1hdC1lcnJvclxuICAgICAgICAgICAgICAqbmdJZj1cInNldHRpbmdzRm9ybT8uY29udHJvbHMubG9jYWxlLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIHNldHRpbmdzRm9ybT8uY29udHJvbHMubG9jYWxlLmRpcnR5XCJcbiAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuXG4gICAgICAgICAgPCEtLSBsYXQvbG9uZyBmb3JtYXQtLT5cbiAgICAgICAgICBAaWYgKHNob3dMYXRMb25Gb3JtYXQpIHtcbiAgICAgICAgICAgIEBsZXQgY29udHJvbCA9IHNldHRpbmdzRm9ybSB8IGZvcm1HZXRDb250cm9sOiAnbGF0TG9uZ0Zvcm1hdCc7XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ0FDQ09VTlQuU0VUVElOR1MuTEFUX0xPTkdfRk9STUFUJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBbZm9ybUNvbnRyb2xdPVwiY29udHJvbFwiIHJlcXVpcmVkPlxuICAgICAgICAgICAgICAgIEBmb3IgKGl0ZW0gb2YgbGF0TG9uZ0Zvcm1hdHM7IHRyYWNrIGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJpdGVtXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7ICdDT01NT04uTEFUX0xPTkcuRU5VTS4nICsgaXRlbSB8IHVwcGVyY2FzZSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICBAaWYgKGNvbnRyb2wuZGlydHkgJiYgY29udHJvbC5oYXNFcnJvcigncmVxdWlyZWQnKSkge1xuICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgdHJhbnNsYXRlPkVSUk9SLkZJRUxEX1JFUVVJUkVEPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIE9wdGlvbnMgdGFibGUgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJvcHRpb25zLXRhYmxlXCIgW2NsYXNzLmNkay12aXN1YWxseS1oaWRkZW5dPVwib3B0aW9uRGVmaW5pdGlvbnMgfCBpc0VtcHR5QXJyYXlcIj5cbiAgICAgICAgICA8YXBwLXByb3BlcnRpZXMtdGFibGVcbiAgICAgICAgICAgICNwcm9wZXJ0aWVzVGFibGVcbiAgICAgICAgICAgIGkxOG5Db2x1bW5QcmVmaXg9XCJBQ0NPVU5ULlNFVFRJTkdTLk9QVElPTlMuXCJcbiAgICAgICAgICAgIFtkZWZpbml0aW9uc109XCJvcHRpb25EZWZpbml0aW9uc1wiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgW2NhbkVkaXRdPVwidHJ1ZVwiXG4gICAgICAgICAgICBbZGVidWddPVwiZGVidWdcIlxuICAgICAgICAgICAgKG9uRGlydHkpPVwiJGV2ZW50ID8gbWFya0FzRGlydHkoKSA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgPjwvYXBwLXByb3BlcnRpZXMtdGFibGU+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9tYXQtdGFiPlxuXG4gICAgICA8IS0tIFRBQjogdG9rZW5zIC0tPlxuICAgICAgPG1hdC10YWIgW2xhYmVsXT1cIidBQ0NPVU5ULlRPS0VOUy5USVRMRScgfCB0cmFuc2xhdGVcIiBmb3JtR3JvdXBOYW1lPVwidG9rZW5zXCIgW2Rpc2FibGVkXT1cIiFzaG93QXBpVG9rZW5zXCI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSBtYXQtdGFiLWxhYmVsPlxuICAgICAgICAgIDxtYXQtaWNvbj5cbiAgICAgICAgICAgIDxpb24taWNvbiBtYXRQcmVmaXggc2xvdD1cInN0YXJ0XCIgbmFtZT1cInRpY2tldFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgPC9tYXQtaWNvbj5cbiAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5BQ0NPVU5ULlRPS0VOUy5USVRMRTwvaW9uLWxhYmVsPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpb24tcGFkZGluZ1wiPlxuICAgICAgICAgIDxwIFtpbm5lckhUTUxdPVwiJ0FDQ09VTlQuVE9LRU5TLkRFU0NSSVBUSU9OJyB8IHRyYW5zbGF0ZVwiPjwvcD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDwhLS0gVG9rZW5zIHRhYmxlIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidG9rZW5zLXRhYmxlXCI+XG4gICAgICAgICAgPGFwcC11c2VyLXRva2VuLXRhYmxlXG4gICAgICAgICAgICAjdG9rZW5zVGFibGVcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBbY2FuRWRpdF09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtkZWJ1Z109XCJkZWJ1Z1wiXG4gICAgICAgICAgICAob25EaXJ0eSk9XCIkZXZlbnQgPyBtYXJrQXNEaXJ0eSgpIDogdW5kZWZpbmVkXCJcbiAgICAgICAgICA+PC9hcHAtdXNlci10b2tlbi10YWJsZT5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L21hdC10YWI+XG4gICAgPC9tYXQtdGFiLWdyb3VwPlxuICA8L2Zvcm0+XG48L2lvbi1jb250ZW50PlxuXG48aW9uLWZvb3RlciBoaWRkZW4teHMgaGlkZGVuLXNtIGhpZGRlbi1tb2JpbGU+XG4gIDxhcHAtZm9ybS1idXR0b25zLWJhciAob25DYW5jZWwpPVwiY2FuY2VsKClcIiAob25TYXZlKT1cInNhdmUoKVwiIFtkaXNhYmxlZF09XCIhZm9ybS5kaXJ0eSB8fCAhdmFsaWQgfHwgc2F2aW5nXCI+XG4gICAgPCEtLSBlcnJvciAtLT5cbiAgICA8aW9uLWl0ZW0gKm5nSWY9XCJlcnJvciAmJiAhbW9iaWxlXCIgbGluZXM9XCJub25lXCI+XG4gICAgICA8aW9uLWljb24gY29sb3I9XCJkYW5nZXJcIiBzbG90PVwic3RhcnRcIiBuYW1lPVwiYWxlcnQtY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICAgIDxpb24tbGFiZWwgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cImVycm9yXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgIDwvaW9uLWl0ZW0+XG4gIDwvYXBwLWZvcm0tYnV0dG9ucy1iYXI+XG48L2lvbi1mb290ZXI+XG4iXX0=
|
|
426
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiYWNjb3VudC5wYWdlLmpzIiwic291cmNlUm9vdCI6IiIsInNvdXJjZXMiOlsiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL2FjY291bnQvYWNjb3VudC5wYWdlLnRzIiwiLi4vLi4vLi4vLi4vLi4vLi4vc3JjL2FwcC9jb3JlL2FjY291bnQvYWNjb3VudC5wYWdlLmh0bWwiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLHVCQUF1QixFQUFxQixTQUFTLEVBQUUsWUFBWSxFQUFFLE1BQU0sRUFDbEYsUUFBUSxFQUFFLFNBQVMsRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUM3QyxPQUFPLEVBQUUsYUFBYSxFQUFnQixNQUFNLE1BQU0sQ0FBQztBQUVuRCxPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0saUNBQWlDLENBQUM7QUFDMUQsT0FBTyxFQUF3QyxVQUFVLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUVsRixPQUFPLEVBQUUsT0FBTyxFQUFFLE1BQU0sb0JBQW9CLENBQUM7QUFDN0MsT0FBTyxFQUFFLFlBQVksRUFBWSxNQUFNLG9CQUFvQixDQUFDO0FBRTVELE9BQU8sRUFBRSxpQkFBaUIsRUFBRSxNQUFNLDZDQUE2QyxDQUFDO0FBQ2hGLE9BQU8sRUFBRSxTQUFTLEVBQUUsTUFBTSw4QkFBOEIsQ0FBQztBQUN6RCxPQUFPLEVBQUUsV0FBVyxFQUErQixNQUFNLGtDQUFrQyxDQUFDO0FBRTVGLE9BQU8sRUFBRSxNQUFNLEVBQUUsR0FBRyxFQUFFLE1BQU0sZ0JBQWdCLENBQUM7QUFHN0MsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sZ0NBQWdDLENBQUM7QUFDckUsT0FBTyxFQUFzQixjQUFjLEVBQUUsTUFBTSxxQ0FBcUMsQ0FBQztBQUV6RixPQUFPLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsTUFBTSx3QkFBd0IsQ0FBQztBQU9wRixPQUFPLEVBQUUsV0FBVyxFQUFlLE1BQU0seUNBQXlDLENBQUM7QUFDbkYs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LFlBQVksRUFBRSxDQUFDO0lBQ3RCLENBQUM7SUFFUyxzQkFBc0I7UUFDOUIsT0FBTyxJQUFJLENBQUMsYUFBYSxDQUFDLGVBQWUsQ0FBQyxrQkFBa0IsQ0FBQyxDQUFDO0lBQ2hFLENBQUM7SUFFUyxZQUFZO1FBQ3BCLElBQUksQ0FBQyxFQUFFLENBQUMsWUFBWSxFQUFFLENBQUM7SUFDekIsQ0FBQztJQUVTLFlBQVk7UUFDcEIsSUFBSSxDQUFDLE1BQU0sR0FBRyxJQUFJLENBQUM7SUFDckIsQ0FBQztJQUVTLFdBQVc7UUFDbkIsSUFBSSxDQUFDLE1BQU0sR0FBRyxLQUFLLENBQUM7SUFDdEIsQ0FBQzt3R0FyWlUsV0FBVyxzU0E2RFosV0FBVyxhQUNYLFdBQVcsYUFDQyxhQUFhOzRGQS9EeEIsV0FBVywwZUNyQ3hCLGcrZUE0VkE7OzRGRHZUYSxXQUFXO2tCQU52QixTQUFTOytCQUNFLGtCQUFrQixtQkFHWCx1QkFBdUIsQ0FBQyxNQUFNOzswQkErRDVDLE1BQU07MkJBQUMsV0FBVzs7MEJBQ2xCLE1BQU07MkJBQUMsV0FBVzs7MEJBQ2xCLFFBQVE7OzBCQUFJLE1BQU07MkJBQUMsYUFBYTt5Q0E5RE0sUUFBUTtzQkFBaEQsU0FBUzt1QkFBQyxVQUFVLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNTLGVBQWU7c0JBQTlELFNBQVM7dUJBQUMsaUJBQWlCLEVBQUUsRUFBRSxNQUFNLEVBQUUsSUFBSSxFQUFFO2dCQUNGLFdBQVc7c0JBQXRELFNBQVM7dUJBQUMsYUFBYSxFQUFFLEVBQUUsTUFBTSxFQUFFLElBQUksRUFBRTtnQkE0VzFDLGFBQWE7c0JBRFosWUFBWTt1QkFBQyxxQkFBcUIsRUFBRSxDQUFDLFFBQVEsQ0FBQyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENoYW5nZURldGVjdGlvblN0cmF0ZWd5LCBDaGFuZ2VEZXRlY3RvclJlZiwgQ29tcG9uZW50LCBIb3N0TGlzdGVuZXIsIEluamVjdCwgSW5qZWN0b3IsIE9uRGVzdHJveSwgT25Jbml0LFxuICBPcHRpb25hbCwgVmlld0NoaWxkIH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBjb21iaW5lTGF0ZXN0LCBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IEFjY291bnRTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvYWNjb3VudC5zZXJ2aWNlJztcbmltcG9ydCB7IEFjY291bnQgfSBmcm9tICcuLi9zZXJ2aWNlcy9tb2RlbC9hY2NvdW50Lm1vZGVsJztcbmltcG9ydCB7IFVudHlwZWRGb3JtQnVpbGRlciwgVW50eXBlZEZvcm1Hcm91cCwgVmFsaWRhdG9ycyB9IGZyb20gJ0Bhbmd1bGFyL2Zvcm1zJztcbmltcG9ydCB7IEFjY291bnRWYWxpZGF0b3JTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvdmFsaWRhdG9yL2FjY291bnQudmFsaWRhdG9yJztcbmltcG9ydCB7IEFwcEZvcm0gfSBmcm9tICcuLi9mb3JtL2Zvcm0uY2xhc3MnO1xuaW1wb3J0IHsgQXBwRm9ybVV0aWxzLCBDYW5MZWF2ZSB9IGZyb20gJy4uL2Zvcm0vZm9ybS51dGlscyc7XG5pbXBvcnQgeyBGb3JtRmllbGREZWZpbml0aW9uIH0gZnJvbSAnLi4vLi4vc2hhcmVkL2Zvcm0vZmllbGQubW9kZWwnO1xuaW1wb3J0IHsgTEFUX0xPTkdfUEFUVEVSTlMgfSBmcm9tICcuLi8uLi9zaGFyZWQvbWF0ZXJpYWwvbGF0bG9uZy9sYXRsb25nLnV0aWxzJztcbmltcG9ydCB7IFN0YXR1c0lkcyB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL21vZGVsLmVudW0nO1xuaW1wb3J0IHsgQVBQX0xPQ0FMRVMsIExvY2FsZUNvbmZpZywgTG9jYWxTZXR0aW5ncyB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL3NldHRpbmdzLm1vZGVsJztcbmltcG9ydCB7IE5ldHdvcmtTZXJ2aWNlIH0gZnJvbSAnLi4vc2VydmljZXMvbmV0d29yay5zZXJ2aWNlJztcbmltcG9ydCB7IGZpbHRlciwgbWFwIH0gZnJvbSAncnhqcy9vcGVyYXRvcnMnO1xuaW1wb3J0IHsgTWF0VGFiR3JvdXAgfSBmcm9tICdAYW5ndWxhci9tYXRlcmlhbC90YWJzJztcbmltcG9ydCB7IENvbmZpZ1NlcnZpY2UgfSBmcm9tICcuLi9zZXJ2aWNlcy9jb25maWcuc2VydmljZSc7XG5pbXBvcnQgeyBDT1JFX0NPTkZJR19PUFRJT05TIH0gZnJvbSAnLi4vc2VydmljZXMvY29uZmlnL2NvcmUuY29uZmlnJztcbmltcG9ydCB7IEFwcFByb3BlcnRpZXNUYWJsZSwgUHJvcGVydHlFbnRpdHkgfSBmcm9tICcuLi9mb3JtL3Byb3BlcnRpZXMvcHJvcGVydGllcy50YWJsZSc7XG5pbXBvcnQgeyBQcm9wZXJ0eU1hcCB9IGZyb20gJy4uLy4uL3NoYXJlZC90eXBlcyc7XG5pbXBvcnQgeyBmaXJzdEFycmF5VmFsdWUsIGlzTm90RW1wdHlBcnJheSwgaXNOb3ROaWwgfSBmcm9tICcuLi8uLi9zaGFyZWQvZnVuY3Rpb25zJztcbmltcG9ydCB7IFVzZXJUb2tlblRhYmxlIH0gZnJvbSAnLi90b2tlbi50YWJsZSc7XG5pbXBvcnQgeyBOYXZDb250cm9sbGVyIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgQ29uZmlndXJhdGlvbiB9IGZyb20gJy4uL3NlcnZpY2VzL21vZGVsL2NvbmZpZy5tb2RlbCc7XG5cbmltcG9ydCB7IEF1dGhUb2tlblR5cGUgfSBmcm9tICcuLi9zZXJ2aWNlcy9uZXR3b3JrLnR5cGVzJztcbmltcG9ydCB7IEltYWdlU2VydmljZSB9IGZyb20gJy4uLy4uL3NoYXJlZC9pbWFnZS9pbWFnZS5zZXJ2aWNlJztcbmltcG9ydCB7IEVOVklST05NRU5ULCBFbnZpcm9ubWVudCB9IGZyb20gJy4uLy4uLy4uL2Vudmlyb25tZW50cy9lbnZpcm9ubWVudC5jbGFzcyc7XG5pbXBvcnQgeyBBUFBfQkFTRV9IUkVGIH0gZnJvbSAnQGFuZ3VsYXIvY29tbW9uJztcbmltcG9ydCB7IFBlcnNvblV0aWxzIH0gZnJvbSAnLi4vc2VydmljZXMvbW9kZWwvcGVyc29uLm1vZGVsJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnYXBwLWFjY291bnQtcGFnZScsXG4gIHRlbXBsYXRlVXJsOiAnYWNjb3VudC5wYWdlLmh0bWwnLFxuICBzdHlsZVVybHM6IFsnLi9hY2NvdW50LnBhZ2Uuc2NzcyddLFxuICBjaGFuZ2VEZXRlY3Rpb246IENoYW5nZURldGVjdGlvblN0cmF0ZWd5Lk9uUHVzaCxcbn0pXG5leHBvcnQgY2xhc3MgQWNjb3VudFBhZ2UgZXh0ZW5kcyBBcHBGb3JtPEFjY291bnQ+IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3ksIENhbkxlYXZlIHtcbiAgQFZpZXdDaGlsZCgndGFiR3JvdXAnLCB7IHN0YXRpYzogdHJ1ZSB9KSB0YWJHcm91cDogTWF0VGFiR3JvdXA7XG4gIEBWaWV3Q2hpbGQoJ3Byb3BlcnRpZXNUYWJsZScsIHsgc3RhdGljOiB0cnVlIH0pIHByb3BlcnRpZXNUYWJsZTogQXBwUHJvcGVydGllc1RhYmxlO1xuICBAVmlld0NoaWxkKCd0b2tlbnNUYWJsZScsIHsgc3RhdGljOiB0cnVlIH0pIHRva2Vuc1RhYmxlOiBVc2VyVG9rZW5UYWJsZTtcblxuICBwcm90ZWN0ZWQgc2VsZWN0ZWRUYWJJbmRleCA9IDA7XG4gIHByb3RlY3RlZCBpc0xvZ2luOiBib29sZWFuO1xuICBwcm90ZWN0ZWQgY2hhbmdlc1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBwcm90ZWN0ZWQgbmV0d29ya1N1YnNjcmlwdGlvbjogU3Vic2NyaXB0aW9uO1xuICBwcm90ZWN0ZWQgZW1haWwgPSB7XG4gICAgY29uZmlybWVkOiBmYWxzZSxcbiAgICBub3RDb25maXJtZWQ6IGZhbHNlLFxuICAgIHNlbmRpbmc6IGZhbHNlLFxuICAgIGVycm9yOiB1bmRlZmluZWQsXG4gIH07XG4gIHByb3RlY3RlZCBhZGRpdGlvbmFsRmllbGRzOiBGb3JtRmllbGREZWZpbml0aW9uW107XG4gIHByb3RlY3RlZCBvcHRpb25EZWZpbml0aW9uczogRm9ybUZpZWxkRGVmaW5pdGlvbltdO1xuXG4gIGdldCBzZXR0aW5nc0Zvcm0oKTogVW50eXBlZEZvcm1Hcm91cCB7XG4gICAgcmV0dXJuIHRoaXMuZm9ybS5nZXQoJ3NldHRpbmdzJykgYXMgVW50eXBlZEZvcm1Hcm91cDtcbiAgfVxuXG4gIC8vIHNldHRpbmdzQ29udGVudEZvcm06IFVudHlwZWRGb3JtR3JvdXA7XG4gIHByb3RlY3RlZCBsb2NhbGVzOiBMb2NhbGVDb25maWdbXTtcbiAgcHJvdGVjdGVkIGxhdExvbmdGb3JtYXRzID0gTEFUX0xPTkdfUEFUVEVSTlM7XG4gIHByb3RlY3RlZCBzYXZpbmcgPSBmYWxzZTtcbiAgcHJvdGVjdGVkIHN1Ym1pdHRlZCA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgYWNjb3VudFJlYWRPbmx5ID0gZmFsc2U7XG4gIHByb3RlY3RlZCByZWFkb25seSBkZWZhdWx0QXZhdGFySW1hZ2UgPSBQZXJzb25VdGlscy5ERUZBVUxUX0FWQVRBUl9JTUFHRTtcbiAgcHJvdGVjdGVkIHJlYWRvbmx5IG1vYmlsZTogYm9vbGVhbjtcblxuICBnZXQgdmFsaWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHN1cGVyLnZhbGlkICYmICh0aGlzLnByb3BlcnRpZXNUYWJsZT8udmFsaWQgfHwgdHJ1ZSk7XG4gIH1cblxuICBnZXQgaW52YWxpZCgpOiBib29sZWFuIHtcbiAgICByZXR1cm4gc3VwZXIuaW52YWxpZCAmJiAodGhpcy5wcm9wZXJ0aWVzVGFibGUgPyB0aGlzLnByb3BlcnRpZXNUYWJsZS5pbnZhbGlkIDogZmFsc2UpO1xuICB9XG5cbiAgZ2V0IGRpcnR5KCk6IGJvb2xlYW4ge1xuICAgIHJldHVybiBzdXBlci5kaXJ0eSB8fCB0aGlzLnByb3BlcnRpZXNUYWJsZT8uZGlydHkgfHwgZmFsc2U7XG4gIH1cblxuICBwcm90ZWN0ZWQgc2hvd0xhdExvbkZvcm1hdCA9IHRydWU7XG4gIHByb3RlY3RlZCBjYW5DaGFuZ2VQYXNzd29yZCA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgc2hvd1NlY3VyaXR5RGV0YWlscyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgc2hvd1RlY2huaWNhbERldGFpbHMgPSB0cnVlO1xuICBwcm90ZWN0ZWQgc2hvd0FwaVRva2VucyA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgc2hvd0F2YXRhciA9IGZhbHNlO1xuICBwcm90ZWN0ZWQgYXZhdGFyTWF4U2l6ZTogbnVtYmVyO1xuXG4gIGNvbnN0cnVjdG9yKFxuICAgIGluamVjdG9yOiBJbmplY3RvcixcbiAgICBwdWJsaWMgZm9ybUJ1aWxkZXI6IFVudHlwZWRGb3JtQnVpbGRlcixcbiAgICBwdWJsaWMgYWNjb3VudFNlcnZpY2U6IEFjY291bnRTZXJ2aWNlLFxuICAgIHB1YmxpYyBuZXR3b3JrOiBOZXR3b3JrU2VydmljZSxcbiAgICBwcm90ZWN0ZWQgbmF2Q29udHJvbGxlcjogTmF2Q29udHJvbGxlcixcbiAgICBwcm90ZWN0ZWQgdmFsaWRhdG9yU2VydmljZTogQWNjb3VudFZhbGlkYXRvclNlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNvbmZpZ1NlcnZpY2U6IENvbmZpZ1NlcnZpY2UsXG4gICAgcHJvdGVjdGVkIGNkOiBDaGFuZ2VEZXRlY3RvclJlZixcbiAgICBwcm90ZWN0ZWQgaW1hZ2VTZXJ2aWNlOiBJbWFnZVNlcnZpY2UsXG4gICAgQEluamVjdChFTlZJUk9OTUVOVCkgZW52aXJvbm1lbnQ6IEVudmlyb25tZW50LFxuICAgIEBJbmplY3QoQVBQX0xPQ0FMRVMpIGxvY2FsZXM6IExvY2FsZUNvbmZpZ1tdLFxuICAgIEBPcHRpb25hbCgpIEBJbmplY3QoQVBQX0JBU0VfSFJFRikgcHJvdGVjdGVkIGFwcEJhc2VIcmVmOiBzdHJpbmcsXG4gICkge1xuICAgIHN1cGVyKGluamVjdG9yLCB2YWxpZGF0b3JTZXJ2aWNlLmdldEZvcm1Hcm91cChhY2NvdW50U2VydmljZS5hY2NvdW50LCB7IHdpdGhTZXR0aW5nczogdHJ1ZSB9KSk7XG5cbiAgICB0aGlzLmxvY2FsZXMgPSBsb2NhbGVzO1xuICAgIHRoaXMubW9iaWxlID0gdGhpcy5zZXR0aW5ncy5tb2JpbGU7XG4gICAgdGhpcy5kZWJ1ZyA9ICFlbnZpcm9ubWVudC5wcm9kdWN0aW9uO1xuXG4gICAgLy8gQnkgZGVmYXVsdCwgZGlzYWJsZSB0aGUgZm9ybVxuICAgIHRoaXMuZGlzYWJsZSgpO1xuICB9XG5cbiAgbmdPbkluaXQoKSB7XG4gICAgc3VwZXIubmdPbkluaXQoKTtcblxuICAgIC8vIEdldCB1c2VyIG9wdGlvbnNcbiAgICB0aGlzLm9wdGlvbkRlZmluaXRpb25zID0gKHRoaXMuYWNjb3VudFNlcnZpY2Uub3B0aW9uRGVmcyB8fCBbXSkuZmlsdGVyKFxuICAgICAgKGRlZmluaXRpb24pID0+ICFkZWZpbml0aW9uLmRpc2FibGVkICYmICghZGVmaW5pdGlvbi5taW5Qcm9maWxlIHx8IHRoaXMuYWNjb3VudFNlcnZpY2UuaGFzTWluUHJvZmlsZShkZWZpbml0aW9uLm1pblByb2ZpbGUpKVxuICAgICk7XG5cbiAgICAvLyBPYnNlcnZlZCBzb21lIGV2ZW50c1xuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24odGhpcy5hY2NvdW50U2VydmljZS5vbkxvZ2luLnBpcGUoZmlsdGVyKCgpID0+ICF0aGlzLnNhdmluZykpLnN1YnNjcmliZSgoYWNjb3VudCkgPT4gdGhpcy5vbkxvZ2luKGFjY291bnQpKSk7XG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbih0aGlzLmFjY291bnRTZXJ2aWNlLm9uTG9nb3V0LnN1YnNjcmliZSgoKSA9PiB0aGlzLm9uTG9nb3V0KCkpKTtcbiAgICB0aGlzLnJlZ2lzdGVyU3Vic2NyaXB0aW9uKFxuICAgICAgdGhpcy5vbkNhbmNlbC5zdWJzY3JpYmUoKCkgPT4ge1xuICAgICAgICB0aGlzLnNldFZhbHVlKHRoaXMuYWNjb3VudFNlcnZpY2UuYWNjb3VudCk7XG4gICAgICAgIHRoaXMubWFya0FzUHJpc3RpbmUoKTtcbiAgICAgIH0pXG4gICAgKTtcblxuICAgIHRoaXMucmVnaXN0ZXJTdWJzY3JpcHRpb24oXG4gICAgICB0aGlzLmFjY291bnRTZXJ2aWNlLmFkZGl0aW9uYWxGaWVsZHMkLnN1YnNjcmliZSgoYWRkaXRpb25hbEZpZWxkcykgPT4ge1xuICAgICAgICB0aGlzLmFkZGl0aW9uYWxGaWVsZHMgPSBhZGRpdGlvbmFsRmllbGRzLmZpbHRlcigoZmllbGQpID0+IGZpZWxkLmV4dHJhPy5hY2NvdW50KTtcbiAgICAgICAgaWYgKHRoaXMuYWNjb3VudFNlcnZpY2UuaXNMb2dpbigpKSB7XG4gICAgICAgICAgdGhpcy5vbkxvZ2luKHRoaXMuYWNjb3VudFNlcnZpY2UuYWNjb3VudCk7XG4gICAgICAgIH0gZWxzZSB7XG4gICAgICAgICAgdGhpcy5tYXJrQXNMb2FkZWQoKTtcbiAgICAgICAgfVxuICAgICAgfSlcbiAgICApO1xuXG4gICAgdGhpcy5yZWdpc3RlclN1YnNjcmlwdGlvbih0aGlzLmNvbmZpZ1NlcnZpY2UuY29uZmlnLnN1YnNjcmliZSgoY29uZmlnKSA9PiB0aGlzLm9uQ29uZmlnTG9hZGVkKGNvbmZpZykpKTtcblxuICAgIC8vIFJlYWxpZ24gdGFiLCBhZnRlciBhIGRlbGF5IGJlY2F1c2UgdGhlIHRhYiBjYW4gYmUgZGlzYWJsZWQgd2hlbiBjb21wb25lbnQgaXMgY3JlYXRlZFxuICAgIHNldFRpbWVvdXQoKCkgPT4gdGhpcy50YWJHcm91cC5yZWFsaWduSW5rQmFyKCksIDUwMCk7XG4gIH1cblxuICBhc3luYyBvbkNoYW5nZUF2YXRhcihldmVudDogRXZlbnQpIHtcbiAgICBpZiAoIXRoaXMuc2hvd0F2YXRhciB8fCBldmVudC5kZWZhdWx0UHJldmVudGVkIHx8IHRoaXMuZGlzYWJsZWQpIHJldHVybjtcblxuICAgIGV2ZW50LnByZXZlbnREZWZhdWx0KCk7XG4gICAgZXZlbnQuc3RvcFByb3BhZ2F0aW9uKCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgaW1hZ2VzID0gYXdhaXQgdGhpcy5pbWFnZVNlcnZpY2UuYWRkKGV2ZW50LCB7IG11bHRpcGxlOiBmYWxzZSxcbiAgICAgICAgYXV0b0hpZGVEcm9wQXJlYTogdHJ1ZSxcbiAgICAgICAgc3R5bGU6ICdjYW1lcmEnLCAvLyBGb3JjZSB0byB1c2UgdGhlIGNhbWVyYSAoaWYgQ2FwYWNpdG9yIGlzIGVuYWJsZWQpXG4gICAgICAgIHdpZHRoOiB0aGlzLmF2YXRhck1heFNpemUsXG4gICAgICAgIGhlaWdodDogdGhpcy5hdmF0YXJNYXhTaXplLFxuICAgICAgfSk7XG4gICAgICBjb25zdCBpbWcgPSBmaXJzdEFycmF5VmFsdWUoaW1hZ2VzKTtcbiAgICAgIGlmICghaW1nPy5kYXRhVXJsKSByZXR1cm47XG4gICAgICBjb25zdCBjb250cm9sID0gdGhpcy5mb3JtLmdldCgnYXZhdGFyJyk7XG4gICAgICBpZiAoY29udHJvbCkge1xuICAgICAgICBjb250cm9sLnNldFZhbHVlKGltZy5kYXRhVXJsKTtcbiAgICAgICAgY29udHJvbC5tYXJrQXNEaXJ0eSgpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgLy8gRmFsbGJhY2sgaWYgY29udHJvbCBtaXNzaW5nOiBwYXRjaCB2YWx1ZSBhbmQgbWFyayBmb3JtIGRpcnR5XG4gICAgICAgIHRoaXMuZm9ybS5wYXRjaFZhbHVlKHsgYXZhdGFyOiBpbWcuZGF0YVVybCB9KTtcbiAgICAgICAgdGhpcy5mb3JtLm1hcmtBc0RpcnR5KCk7XG4gICAgICB9XG4gICAgICB0aGlzLm1hcmtGb3JDaGVjaygpO1xuICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgY29uc29sZS5lcnJvcignW2FjY291bnRdIEVycm9yIHdoaWxlIGNoYW5naW5nIGF2YXRhcjonLCBlcnI/Lm1lc3NhZ2UgfHwgZXJyKTtcbiAgICB9XG4gIH1cblxuICBuZ09uRGVzdHJveSgpIHtcbiAgICBzdXBlci5uZ09uRGVzdHJveSgpO1xuICAgIHRoaXMuc3RvcExpc3RlbkNoYW5nZXMoKTtcbiAgICB0aGlzLm5ldHdvcmtTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gIH1cblxuICBvbkxvZ2luKGFjY291bnQ6IEFjY291bnQpIHtcbiAgICBjb25zb2xlLmRlYnVnKCdbYWNjb3VudF0gTG9nZ2VkIGFjY291bnQ6ICcsIGFjY291bnQpO1xuICAgIHRoaXMuaXNMb2dpbiA9IHRydWU7XG5cbiAgICB0aGlzLnNldFZhbHVlKGFjY291bnQpO1xuXG4gICAgdGhpcy5lbWFpbC5jb25maXJtZWQgPSBhY2NvdW50ICYmIGFjY291bnQuZW1haWwgJiYgYWNjb3VudC5zdGF0dXNJZCAhPT0gU3RhdHVzSWRzLlRFTVBPUkFSWTtcbiAgICB0aGlzLmVtYWlsLm5vdENvbmZpcm1lZCA9IGFjY291bnQgJiYgYWNjb3VudC5lbWFpbCAmJiAoIWFjY291bnQuc3RhdHVzSWQgfHwgYWNjb3VudC5zdGF0dXNJZCA9PT0gU3RhdHVzSWRzLlRFTVBPUkFSWSk7XG5cbiAgICB0aGlzLm5ldHdvcmtTdWJzY3JpcHRpb24/LnVuc3Vic2NyaWJlKCk7XG4gICAgdGhpcy5uZXR3b3JrU3Vic2NyaXB0aW9uID0gY29tYmluZUxhdGVzdChbXG4gICAgICB0aGlzLmNvbmZpZ1NlcnZpY2UuY29uZmlnLFxuICAgICAgdGhpcy5uZXR3b3JrLm9uTmV0d29ya1N0YXR1c0NoYW5nZXMucGlwZShtYXAoKGNvbm5lY3Rpb25UeXBlKSA9PiBjb25uZWN0aW9uVHlwZSAhPT0gJ25vbmUnKSksXG4gICAgXSkuc3Vic2NyaWJlKChbY29uZmlnLCBvbmxpbmVdKSA9PiB7XG4gICAgICB0aGlzLm9uQ29uZmlnTG9hZGVkKGNvbmZpZyk7XG5cbiAgICAgIGlmIChvbmxpbmUpIHtcbiAgICAgICAgdGhpcy5lbmFibGUoKTtcbiAgICAgICAgdGhpcy5tYXJrQXNQcmlzdGluZSgpO1xuICAgICAgICB0aGlzLnN0YXJ0TGlzdGVuQ2hhbmdlcygpO1xuICAgICAgfSBlbHNlIHtcbiAgICAgICAgdGhpcy5kaXNhYmxlKCk7XG4gICAgICAgIHRoaXMubWFya0FzUHJpc3RpbmUoKTtcbiAgICAgICAgdGhpcy5zdG9wTGlzdGVuQ2hhbmdlcygpO1xuICAgICAgfVxuICAgICAgdGhpcy5tYXJrQXNMb2FkZWQoKTtcbiAgICB9KTtcblxuICAgIHRoaXMubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBvbkxvZ291dCgpIHtcbiAgICB0aGlzLmlzTG9naW4gPSBmYWxzZTtcbiAgICB0aGlzLmVtYWlsLmNvbmZpcm1lZCA9IGZhbHNlO1xuICAgIHRoaXMuZW1haWwubm90Q29uZmlybWVkID0gZmFsc2U7XG4gICAgdGhpcy5lbWFpbC5zZW5kaW5nID0gZmFsc2U7XG4gICAgdGhpcy5lbWFpbC5lcnJvciA9IHVuZGVmaW5lZDtcbiAgICB0aGlzLmZvcm0ucmVzZXQoKTtcbiAgICB0aGlzLmRpc2FibGUoKTtcblxuICAgIHRoaXMubmV0d29ya1N1YnNjcmlwdGlvbj8udW5zdWJzY3JpYmUoKTtcblxuICAgIHRoaXMuc3RvcExpc3RlbkNoYW5nZXMoKTtcblxuICAgIC8vIEJhY2sgdG8gaG9tZVxuICAgIHRoaXMubmF2Q29udHJvbGxlci5uYXZpZ2F0ZVJvb3QoJy8nKTtcbiAgfVxuXG4gIGFzeW5jIHNldFZhbHVlKGRhdGE6IEFjY291bnQsIG9wdHM/OiB7IGVtaXRFdmVudD86IGJvb2xlYW47IG9ubHlTZWxmPzogYm9vbGVhbiB9KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgc3VwZXIuc2V0VmFsdWUoZGF0YSwgb3B0cyk7XG5cbiAgICAvLyBTZXQgb3B0aW9uc1xuICAgIGNvbnN0IHsgcHJvcGVydGllcyB9ID0gZGF0YT8uc2V0dGluZ3M/LmFzTG9jYWxTZXR0aW5ncyh7IGRlZmluaXRpb25zOiB0aGlzLm9wdGlvbkRlZmluaXRpb25zIH0pIHx8IHt9O1xuICAgIGNvbnN0IHByb3BlcnRpZXNFbnRpdGllczogUHJvcGVydHlFbnRpdHlbXSA9IHRoaXMub3B0aW9uRGVmaW5pdGlvbnNcbiAgICAgIC5tYXAoKGRlZmluaXRpb24pID0+IHtcbiAgICAgICAgY29uc3QgdmFsdWUgPSBwcm9wZXJ0aWVzPy5bZGVmaW5pdGlvbi5rZXldO1xuICAgICAgICByZXR1cm4gaXNOb3ROaWwodmFsdWUpID8gUHJvcGVydHlFbnRpdHkuZnJvbU9iamVjdCh7IGRlZmluaXRpb24sIHZhbHVlIH0pIDogbnVsbDtcbiAgICAgIH0pXG4gICAgICAuZmlsdGVyKGlzTm90TmlsKTtcblxuICAgIGlmICh0aGlzLnByb3BlcnRpZXNUYWJsZSkge1xuICAgICAgYXdhaXQgdGhpcy5wcm9wZXJ0aWVzVGFibGUucmVhZHkoKTtcbiAgICAgIHRoaXMucHJvcGVydGllc1RhYmxlLnZhbHVlID0gcHJvcGVydGllc0VudGl0aWVzO1xuICAgIH1cblxuICAgIGlmICh0aGlzLnRva2Vuc1RhYmxlKSB7XG4gICAgICBhd2FpdCB0aGlzLnRva2Vuc1RhYmxlLnJlYWR5KCk7XG4gICAgICB0aGlzLnRva2Vuc1RhYmxlLnZhbHVlID0gZGF0YS50b2tlbnM7XG4gICAgfVxuICB9XG5cbiAgYXN5bmMgcmVmcmVzaChfPzogRXZlbnQpIHtcbiAgICB0aGlzLmRpc2FibGUoKTtcbiAgICB0aGlzLm1hcmtBc0xvYWRpbmcoKTtcblxuICAgIHJldHVybiB0aGlzLmFjY291bnRTZXJ2aWNlLnJlbG9hZCgpO1xuICB9XG5cbiAgc3RhcnRMaXN0ZW5DaGFuZ2VzKCkge1xuICAgIGlmICh0aGlzLmNoYW5nZXNTdWJzY3JpcHRpb24pIHJldHVybjsgLy8gYWxyZWFkeSBzdGFydGVkXG4gICAgdGhpcy5jaGFuZ2VzU3Vic2NyaXB0aW9uID0gdGhpcy5hY2NvdW50U2VydmljZS5saXN0ZW5DaGFuZ2VzKCk7XG4gIH1cblxuICBzdG9wTGlzdGVuQ2hhbmdlcygpIHtcbiAgICBpZiAoIXRoaXMuY2hhbmdlc1N1YnNjcmlwdGlvbikgcmV0dXJuO1xuICAgIHRoaXMuY2hhbmdlc1N1YnNjcmlwdGlvbi51bnN1YnNjcmliZSgpO1xuICAgIHRoaXMuY2hhbmdlc1N1YnNjcmlwdGlvbiA9IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGFzeW5jIHNlbmRDb25maXJtYXRpb25FbWFpbChldmVudDogTW91c2VFdmVudCkge1xuICAgIGNvbnN0IGpzb24gPSB0aGlzLmZvcm0udmFsdWU7XG4gICAganNvbi5lbWFpbCA9IHRoaXMuZm9ybS5jb250cm9sc1snZW1haWwnXS52YWx1ZTtcbiAgICBpZiAoIWpzb24uZW1haWwgfHwgIXRoaXMuZW1haWwubm90Q29uZmlybWVkKSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpO1xuICAgICAgcmV0dXJuIGZhbHNlO1xuICAgIH1cblxuICAgIHRoaXMuZW1haWwuc2VuZGluZyA9IHRydWU7XG4gICAgY29uc29sZS5kZWJ1ZygnW2FjY291bnRdIFNlbmRpbmcgY29uZmlybWF0aW9uIGVtYWlsLi4uJyk7XG4gICAgdHJ5IHtcbiAgICAgIGF3YWl0IHRoaXMuYWNjb3VudFNlcnZpY2Uuc2VuZENvbmZpcm1hdGlvbkVtYWlsKGpzb24uZW1haWwsIChqc29uLnNldHRpbmdzICYmIGpzb24uc2V0dGluZ3MubG9jYWxlKSB8fCB0aGlzLnRyYW5zbGF0ZS5jdXJyZW50TGFuZyk7XG4gICAgICBjb25zb2xlLmRlYnVnKCdbYWNjb3VudF0gQ29uZmlybWF0aW9uIGVtYWlsIHNlbnQuJyk7XG4gICAgICB0aGlzLmVtYWlsLnNlbmRpbmcgPSBmYWxzZTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMuZW1haWwuc2VuZGluZyA9IGZhbHNlO1xuICAgICAgdGhpcy5lbWFpbC5lcnJvciA9IChlcnIgJiYgZXJyLm1lc3NhZ2UpIHx8IGVycjtcbiAgICB9XG4gIH1cblxuICBhc3luYyBzYXZlKGV2ZW50PzogRXZlbnQpOiBQcm9taXNlPGJvb2xlYW4+IHtcbiAgICBpZiAodGhpcy5zYXZpbmcpIHJldHVybiBmYWxzZTsgLy8gQWxyZWFkeSBzYXZpbmc6IHNraXBcblxuICAgIGlmICghdGhpcy5mb3JtLnZhbGlkKSB7XG4gICAgICBhd2FpdCBBcHBGb3JtVXRpbHMud2FpdFdoaWxlUGVuZGluZyh0aGlzLmZvcm0pO1xuXG4gICAgICBpZiAodGhpcy5mb3JtLmludmFsaWQpIHtcbiAgICAgICAgQXBwRm9ybVV0aWxzLmxvZ0Zvcm1FcnJvcnModGhpcy5mb3JtKTtcbiAgICAgICAgdGhpcy5mb3JtLm1hcmtBbGxBc1RvdWNoZWQoKTtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfVxuICAgIH1cblxuICAgIHRoaXMuc3VibWl0dGVkID0gdHJ1ZTtcbiAgICB0aGlzLmVycm9yID0gdW5kZWZpbmVkO1xuICAgIHRoaXMubWFya0FzU2F2aW5nKCk7XG5cbiAgICB0cnkge1xuICAgICAgY29uc3QgZGF0YSA9IEFjY291bnQuZnJvbU9iamVjdCh7XG4gICAgICAgIC4uLnRoaXMuYWNjb3VudFNlcnZpY2UuYWNjb3VudC5hc09iamVjdCgpLFxuICAgICAgICAuLi50aGlzLmZvcm0udmFsdWUsXG4gICAgICB9KTtcblxuICAgICAgaWYgKGlzTm90RW1wdHlBcnJheSh0aGlzLm9wdGlvbkRlZmluaXRpb25zKSAmJiB0aGlzLnByb3BlcnRpZXNUYWJsZSkge1xuICAgICAgICAvLyBNZXJnZSBwcm9wZXJ0aWVzXG4gICAgICAgIGF3YWl0IHRoaXMucHJvcGVydGllc1RhYmxlLnNhdmUoKTtcbiAgICAgICAgY29uc3QgcHJvcGVydHlFbnRpdGllcyA9IHRoaXMucHJvcGVydGllc1RhYmxlLnZhbHVlIHx8IFtdO1xuICAgICAgICBjb25zdCBwcm9wZXJ0aWVzOiBQcm9wZXJ0eU1hcCA9IHByb3BlcnR5RW50aXRpZXMucmVkdWNlKChyZXMsIGl0ZW0pID0+IHtcbiAgICAgICAgICByZXNbaXRlbS5pZF0gPSBpdGVtLnZhbHVlO1xuICAgICAgICAgIHJldHVybiByZXM7XG4gICAgICAgIH0sIHt9KTtcbiAgICAgICAgY29uc3QgbmV3UHJvcGVydGllcyA9IHsgLi4uZGF0YS5zZXR0aW5ncy5jb250ZW50Wydwcm9wZXJ0aWVzJ10sIC4uLnByb3BlcnRpZXMgfTtcbiAgICAgICAgZGF0YS5zZXR0aW5ncy5tZXJnZSg8TG9jYWxTZXR0aW5ncz57IHByb3BlcnRpZXM6IG5ld1Byb3BlcnRpZXMgfSwgWydwcm9wZXJ0aWVzJ10pO1xuICAgICAgfSBlbHNlIGlmIChkYXRhLnNldHRpbmdzLmNvbnRlbnRbJ3Byb3BlcnRpZXMnXSkge1xuICAgICAgICAvLyBDbGVhbiBwcm9wZXJ0aWVzXG4gICAgICAgIGRlbGV0ZSBkYXRhLnNldHRpbmdzLmNvbnRlbnRbJ3Byb3BlcnRpZXMnXTtcbiAgICAgIH1cblxuICAgICAgaWYgKHRoaXMudG9rZW5zVGFibGUpIHtcbiAgICAgICAgYXdhaXQgdGhpcy50b2tlbnNUYWJsZS5zYXZlKCk7XG4gICAgICAgIGRhdGEudG9rZW5zID0gdGhpcy50b2tlbnNUYWJsZS52YWx1ZTtcbiAgICAgIH1cblxuICAgICAgY29uc29sZS5kZWJ1ZygnW2FjY291bnRdIFNhdmluZyBhY2NvdW50Li4uJywgZGF0YSk7XG5cbiAgICAgIHRyeSB7XG4gICAgICAgIHRoaXMuZGlzYWJsZSgpO1xuXG4gICAgICAgIGF3YWl0IHRoaXMuYWNjb3VudFNlcnZpY2Uuc2F2ZShkYXRhKTtcblxuICAgICAgICAvLyBSZWxvYWRcbiAgICAgICAgc2V0VGltZW91dCgoKSA9PiB0aGlzLm9uTG9naW4odGhpcy5hY2NvdW50U2VydmljZS5hY2NvdW50KSwgMTAwKTtcblxuICAgICAgICB0aGlzLm1hcmtBc1ByaXN0aW5lKCk7XG4gICAgICAgIHJldHVybiB0cnVlO1xuICAgICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICAgIGNvbnNvbGUuZXJyb3IoZXJyKTtcbiAgICAgICAgdGhpcy5lcnJvciA9IChlcnIgJiYgZXJyLm1lc3NhZ2UpIHx8IGVycjtcbiAgICAgICAgcmV0dXJuIGZhbHNlO1xuICAgICAgfSBmaW5hbGx5IHtcblxuICAgICAgICB0aGlzLmVuYWJsZSgpO1xuICAgICAgfVxuICAgIH1maW5hbGx5IHtcbiAgICAgIHRoaXMubWFya0FzU2F2ZWQoKTtcbiAgICB9XG4gIH1cblxuICBlbmFibGUob3B0cz86IHsgb25seVNlbGY/OiBib29sZWFuOyBlbWl0RXZlbnQ/OiBib29sZWFuIH0pIHtcbiAgICBzdXBlci5lbmFibGUob3B0cyk7XG5cbiAgICAvLyBTb21lIGZpZWxkcyBhcmUgYWx3YXlzIGRpc2FibGVcbiAgICB0aGlzLmZvcm0uY29udHJvbHMuZW1haWwuZGlzYWJsZSgpO1xuICAgIHRoaXMuZm9ybS5jb250cm9scy5tYWluUHJvZmlsZS5kaXNhYmxlKCk7XG4gICAgdGhpcy5mb3JtLmNvbnRyb2xzLnB1YmtleS5kaXNhYmxlKCk7XG5cbiAgICAvLyBEaXNhYmxlIGFjY291bnQgZmllbGRzIGlmIHJlYWRvbmx5IGJ5IGNvbmZpZ3VyYXRpb25cbiAgICBjb25zdCBkaXNhYmxlZCA9IHRoaXMuYWNjb3VudFJlYWRPbmx5O1xuICAgIGlmIChkaXNhYmxlZCkge1xuICAgICAgdGhpcy5mb3JtLmNvbnRyb2xzLmxhc3ROYW1lLmRpc2FibGUoKTtcbiAgICAgIHRoaXMuZm9ybS5jb250cm9scy5maXJzdE5hbWUuZGlzYWJsZSgpO1xuICAgIH1cblxuICAgIC8vIEFsd2F5cyBkaXNhYmxlIHNvbWUgYWRkaXRpb25hbCBmaWVsZHNcbiAgICB0aGlzLmFkZGl0aW9uYWxGaWVsZHMuZm9yRWFjaCgoZmllbGQpID0+IHtcbiAgICAgIGNvbnN0IGNvbnRyb2wgPSB0aGlzLmZvcm0uY29udHJvbHNbZmllbGQua2V5XTtcbiAgICAgIGlmICghY29udHJvbCkgcmV0dXJuOyAvLyBTa2lwXG5cbiAgICAgIGNvbnN0IGZpZWxkRGlzYWJsZWQgPSBkaXNhYmxlZCB8fCBmaWVsZC5leHRyYT8uYWNjb3VudD8uZGlzYWJsZWQgfHwgZmFsc2U7XG4gICAgICBpZiAoZmllbGREaXNhYmxlZCAmJiBjb250cm9sLmVuYWJsZWQpIHtcbiAgICAgICAgY29udHJvbC5kaXNhYmxlKCk7XG4gICAgICB9XG4gICAgICBjb25zdCByZXF1aXJlZCA9IGZpZWxkLmV4dHJhPy5hY2NvdW50Py5yZXF1aXJlZCA/PyBmYWxzZTtcbiAgICAgIGlmICghZmllbGQucmVxdWlyZWQgJiYgcmVxdWlyZWQpIHtcbiAgICAgICAgY29udHJvbC5zZXRWYWxpZGF0b3JzKGNvbnRyb2wudmFsaWRhdG9yID8gVmFsaWRhdG9ycy5jb21wb3NlKFtjb250cm9sLnZhbGlkYXRvciwgVmFsaWRhdG9ycy5yZXF1aXJlZF0pIDogVmFsaWRhdG9ycy5yZXF1aXJlZCk7XG4gICAgICB9XG4gICAgfSk7XG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIGFzeW5jIGNhbmNlbCgpIHtcbiAgICBhd2FpdCBzdXBlci5jYW5jZWwoKTtcbiAgfVxuXG4gIGFzeW5jIGNsb3NlKF8/OiBFdmVudCkge1xuICAgIGlmICh0aGlzLnNhdmluZykgcmV0dXJuO1xuXG4gICAgLy8gQmFjayB0byBob21lXG4gICAgcmV0dXJuIHRoaXMubmF2Q29udHJvbGxlci5uYXZpZ2F0ZVJvb3QoJy8nKTsgLy8gYmFjayB0byBob21lXG4gIH1cblxuICBASG9zdExpc3RlbmVyKCd3aW5kb3c6YmVmb3JldW5sb2FkJywgWyckZXZlbnQnXSlcbiAgaGFuZGxlUmVmcmVzaChldmVudDogQmVmb3JlVW5sb2FkRXZlbnQpOiB2b2lkIHtcbiAgICAvLyBBdm9pZCB0byBxdWl0IHdlYiBicm93c2VyIHBhZ2UsIHdpdGhvdXQgc2F2aW5nXG4gICAgaWYgKCF0aGlzLm1vYmlsZSAmJiB0aGlzLmRpcnR5KSB7XG4gICAgICBldmVudC5wcmV2ZW50RGVmYXVsdCgpOyAvLyBBdm9pZCB0byBxdWl0IHdpdGhvdXQgc2F2aW5nXG4gICAgfVxuICB9XG5cbiAgcHJvdGVjdGVkIG9uQ29uZmlnTG9hZGVkKGNvbmZpZzogQ29uZmlndXJhdGlvbikge1xuICAgIGNvbnNvbGUuZGVidWcoJ1thY2NvdW50XSBDb25maWcgbG9hZGVkOiAnLCBjb25maWcpO1xuICAgIHRoaXMuYWNjb3VudFJlYWRPbmx5ID0gY29uZmlnLmdldFByb3BlcnR5QXNCb29sZWFuKENPUkVfQ09ORklHX09QVElPTlMuQUNDT1VOVF9SRUFET05MWSk7XG4gICAgdGhpcy5zaG93TGF0TG9uRm9ybWF0ID1cbiAgICAgIGNvbmZpZy5nZXRQcm9wZXJ0eUFzQm9vbGVhbihDT1JFX0NPTkZJR19PUFRJT05TLkFDQ09VTlRfTEFUX0xPTkdfRk9STUFUX0VOQUJMRSkgJiZcbiAgICAgIC8vIEZvciBjb21wYXRpYmlsaXR5IHdpdGggZGVwcmVjYXRlZCBrZXlcbiAgICAgIGNvbmZpZy5nZXRQcm9wZXJ0eUFzQm9vbGVhbihDT1JFX0NPTkZJR19PUFRJT05TLkRFRkFVTFRfTEFUX0xPTkdfRk9STUFUX0VOQUJMRUQpO1xuICAgIHRoaXMuc2hvd0F2YXRhciA9IGNvbmZpZy5nZXRQcm9wZXJ0eUFzQm9vbGVhbihDT1JFX0NPTkZJR19PUFRJT05TLkFDQ09VTlRfQVZBVEFSX0VOQUJMRSk7XG4gICAgdGhpcy5hdmF0YXJNYXhTaXplID0gY29uZmlnLmdldFByb3BlcnR5QXNJbnQoQ09SRV9DT05GSUdfT1BUSU9OUy5BQ0NPVU5UX0FWQVRBUl9NQVhfU0laRSk7XG5cbiAgICBjb25zdCBhdXRoVG9rZW5UeXBlID0gY29uZmlnLmdldFByb3BlcnR5KENPUkVfQ09ORklHX09QVElPTlMuQVVUSF9UT0tFTl9UWVBFKSBhcyBBdXRoVG9rZW5UeXBlO1xuICAgIHRoaXMuY2FuQ2hhbmdlUGFzc3dvcmQgPSBhdXRoVG9rZW5UeXBlID09PSAndG9rZW4nO1xuICAgIHRoaXMuc2hvd1NlY3VyaXR5RGV0YWlscyA9IHRoaXMuY2FuQ2hhbmdlUGFzc3dvcmQ7XG4gICAgdGhpcy5zaG93QXBpVG9rZW5zID0gY29uZmlnLmdldFByb3BlcnR5QXNCb29sZWFuKENPUkVfQ09ORklHX09QVElPTlMuQVVUSF9BUElfVE9LRU5fRU5BQkxFRCk7XG4gICAgdGhpcy5tYXJrRm9yQ2hlY2soKTtcbiAgfVxuXG4gIHByb3RlY3RlZCBvcGVuQ2hhbmdlUGFzc3dvcmRQYWdlKCkge1xuICAgIHJldHVybiB0aGlzLm5hdkNvbnRyb2xsZXIubmF2aWdhdGVGb3J3YXJkKCdhY2NvdW50L3Bhc3N3b3JkJyk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFya0ZvckNoZWNrKCkge1xuICAgIHRoaXMuY2QubWFya0ZvckNoZWNrKCk7XG4gIH1cblxuICBwcm90ZWN0ZWQgbWFya0FzU2F2aW5nKCkge1xuICAgIHRoaXMuc2F2aW5nID0gdHJ1ZTtcbiAgfVxuXG4gIHByb3RlY3RlZCBtYXJrQXNTYXZlZCgpIHtcbiAgICB0aGlzLnNhdmluZyA9IGZhbHNlO1xuICB9XG5cbn1cbiIsIjxhcHAtdG9vbGJhclxuICBbdGl0bGVdPVwiJ0FDQ09VTlQuVElUTEUnIHwgdHJhbnNsYXRlXCJcbiAgY29sb3I9XCJwcmltYXJ5XCJcbiAgW2hhc1ZhbGlkYXRlXT1cImRpcnR5ICYmICFzYXZpbmdcIlxuICBbaGFzQ2xvc2VdPVwiIWRpcnR5ICYmICFzYXZpbmdcIlxuICAob25WYWxpZGF0ZSk9XCJzYXZlKClcIlxuICAob25DbG9zZSk9XCJjbG9zZSgkZXZlbnQpXCJcbj5cbiAgPGlvbi1idXR0b25zIHNsb3Q9XCJlbmRcIj5cbiAgICBAaWYgKGxvYWRpbmcgfHwgc2F2aW5nKSB7XG4gICAgICA8IS0tIGxvYWRlciAtLT5cbiAgICAgIDxpb24tc3Bpbm5lcj48L2lvbi1zcGlubmVyPlxuICAgIH0gQGVsc2UgaWYgKG5ldHdvcmsub25saW5lKSB7XG4gICAgICA8IS0tIHJlZnJlc2ggYnV0dG9uIChpZiBvbmxpbmUpIC0tPlxuICAgICAgPGlvbi1idXR0b24gW21hdFRvb2x0aXBdPVwiJ0NPTU1PTi5CVE5fUkVGUkVTSCcgfCB0cmFuc2xhdGVcIiAoY2xpY2spPVwicmVmcmVzaCgkZXZlbnQpXCI+XG4gICAgICAgIDxtYXQtaWNvbiBzbG90PVwiaWNvbi1vbmx5XCI+cmVmcmVzaDwvbWF0LWljb24+XG4gICAgICA8L2lvbi1idXR0b24+XG4gICAgfVxuICA8L2lvbi1idXR0b25zPlxuPC9hcHAtdG9vbGJhcj5cblxuPGlvbi1jb250ZW50PlxuICA8IS0tIEluc3RhbGwgKGFuZCB1cGdyYWRlKSBjYXJkIC0tPlxuICA8YXBwLWluc3RhbGwtdXBncmFkZS1jYXJkIFtpc0xvZ2luXT1cImlzTG9naW5cIiBbc2hvd0luc3RhbGxCdXR0b25dPVwidHJ1ZVwiPjwvYXBwLWluc3RhbGwtdXBncmFkZS1jYXJkPlxuXG4gIDwhLS0gZXJyb3IgLS0+XG4gIEBpZiAobW9iaWxlICYmIChlcnJvclN1YmplY3QgfCBhc3luYyk7IGFzIGVycm9yKSB7XG4gICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiPlxuICAgICAgPGlvbi1pY29uIGNvbG9yPVwiZGFuZ2VyXCIgc2xvdD1cInN0YXJ0XCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICA8aW9uLWxhYmVsIGNvbG9yPVwiZGFuZ2VyXCIgY2xhc3M9XCJlcnJvclwiIFtpbm5lckhUTUxdPVwiZXJyb3IgfCB0cmFuc2xhdGVcIj48L2lvbi1sYWJlbD5cbiAgICA8L2lvbi1pdGVtPlxuICB9XG5cbiAgPGZvcm0gW2Zvcm1Hcm91cF09XCJmb3JtXCIgbm92YWxpZGF0ZSBjbGFzcz1cImZvcm0tY29udGFpbmVyXCI+XG4gICAgPG1hdC10YWItZ3JvdXBcbiAgICAgICN0YWJHcm91cFxuICAgICAgWyhzZWxlY3RlZEluZGV4KV09XCJzZWxlY3RlZFRhYkluZGV4XCJcbiAgICAgIGNsYXNzPVwibWF0LW1kYy10YWItZGlzYWJsZWQtaGlkZGVuXCJcbiAgICAgIFttYXQtc3RyZXRjaC10YWJzXT1cIm1vYmlsZVwiXG4gICAgICBkeW5hbWljSGVpZ2h0XG4gICAgPlxuICAgICAgPCEtLSBUQUI6IHVzZXIgZGV0YWlscyAtLT5cbiAgICAgIDxtYXQtdGFiIFtsYWJlbF09XCInQUNDT1VOVC5VU0VSX0RFVEFJTFMuVElUTEUnIHwgdHJhbnNsYXRlXCIgY2xhc3M9XCJpb24tcGFkZGluZ1wiPlxuICAgICAgICA8bmctdGVtcGxhdGUgbWF0LXRhYi1sYWJlbD5cbiAgICAgICAgICA8bWF0LWljb24+XG4gICAgICAgICAgICA8aW9uLWljb24gbWF0UHJlZml4IHNsb3Q9XCJzdGFydFwiIG5hbWU9XCJwZXJzb24tY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICAgICAgICA8L21hdC1pY29uPlxuICAgICAgICAgIDxpb24tbGFiZWw+e3sgJ0FDQ09VTlQuVVNFUl9ERVRBSUxTLlRJVExFJyB8IHRyYW5zbGF0ZSB9fTwvaW9uLWxhYmVsPlxuICAgICAgICAgIDxpb24taWNvbiBzbG90PVwiZW5kXCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiIGNvbG9yPVwiZGFuZ2VyXCIgKm5nSWY9XCJzdWJtaXR0ZWQgJiYgZm9ybS5pbnZhbGlkXCI+PC9pb24taWNvbj5cbiAgICAgICAgPC9uZy10ZW1wbGF0ZT5cbiAgICAgICAgPGlvbi1ncmlkIGNsYXNzPVwiaW9uLW5vLXBhZGRpbmdcIj5cbiAgICAgICAgICA8aW9uLXJvdz5cbiAgICAgICAgICAgIDwhLS0gbGVmdCAgbWFyZ2luIC0tPlxuICAgICAgICAgICAgPGlvbi1jb2wgc2l6ZT1cIjBcIiBzaXplLWxnPVwiMVwiIHNpemUteGw9XCIyXCI+Jm5ic3A7PC9pb24tY29sPlxuXG4gICAgICAgICAgICA8aW9uLWNvbCBjbGFzcz1cImlvbi1wYWRkaW5nXCI+XG4gICAgICAgICAgICAgIDwhLS0gQXZhdGFyIGJsb2NrIC0tPlxuICAgICAgICAgICAgICBAaWYgKHNob3dBdmF0YXIpIHtcbiAgICAgICAgICAgICAgICBAbGV0IGFjY291bnRBdmF0YXIgPSBmb3JtPy5jb250cm9scz8uYXZhdGFyPy52YWx1ZSB8fCBmb3JtPy52YWx1ZT8uYXZhdGFyIHx8IGFjY291bnRTZXJ2aWNlPy5hY2NvdW50Py5hdmF0YXIgfHwgZGVmYXVsdEF2YXRhckltYWdlO1xuICAgICAgICAgICAgICAgIEBsZXQgaXNEZWZhdWx0QXZhdGFyID0gYWNjb3VudEF2YXRhcj8uZW5kc1dpdGgoZGVmYXVsdEF2YXRhckltYWdlKTtcbiAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCIgY2xhc3M9XCJpb24tbWFyZ2luLWJvdHRvbVwiIHN0eWxlPVwiLS1pbm5lci1wYWRkaW5nLWVuZDogMFwiPlxuICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gc2xvdD1cInN0YXJ0XCIgZmlsbD1cImNsZWFyXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGNsYXNzPVwidXNlci1hdmF0YXJcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLmJhY2tncm91bmQtaW1hZ2VdPVwiJ3VybCgnICsgKGFjY291bnRBdmF0YXIgfHwgZGVmYXVsdEF2YXRhckltYWdlKSArICcpJ1wiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICAoY2xpY2spPVwib25DaGFuZ2VBdmF0YXIoJGV2ZW50KVwiXG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgW21hdFRvb2x0aXBdPVwiJ0lNQUdFLkJUTl9DQU1FUkFfU09VUkNFJyB8IHRyYW5zbGF0ZVwiXG4gICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgIEBpZiAoIWFjY291bnRSZWFkT25seSAmJiBlbmFibGVkKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIFtjbGFzcy52aXNpYmxlLWhvdmVyXT1cIiFpc0RlZmF1bHRBdmF0YXJcIiBuYW1lPVwiY2FtZXJhXCIgc2xvdD1cImljb24tb25seVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvaW9uLWJ1dHRvbj5cbiAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICAgICAgICB9XG5cbiAgICAgICAgICAgICAgPGlvbi1saXN0LWhlYWRlcj48cCBbaW5uZXJIVE1MXT1cIidBQ0NPVU5ULlVTRVJfREVUQUlMUy5ERVNDUklQVElPTicgfCB0cmFuc2xhdGVcIj48L3A+PC9pb24tbGlzdC1oZWFkZXI+XG5cbiAgICAgICAgICAgICAgPGlvbi1saXN0IFtpbnNldF09XCJtb2JpbGVcIj5cbiAgICAgICAgICAgICAgICA8IS0tIEVtYWlsIC0tPlxuICAgICAgICAgICAgICAgIDxpb24taXRlbSBsaW5lcz1cIm5vbmVcIj5cbiAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnVVNFUi5FTUFJTCcgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IGZvcm1Db250cm9sTmFtZT1cImVtYWlsXCIgYXV0b2NvbXBsZXRlPVwic2VjdGlvbi1yZWQgZW1haWxcIiAvPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5lbWFpbC5oYXNFcnJvcigncmVxdWlyZWQnKSAmJiBmb3JtLmNvbnRyb2xzLmVtYWlsLmRpcnR5XCIgdHJhbnNsYXRlPlxuICAgICAgICAgICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5lbWFpbC5oYXNFcnJvcignZW1haWwnKSAmJiBmb3JtLmNvbnRyb2xzLmVtYWlsLmRpcnR5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX05PVF9WQUxJRF9FTUFJTCcgfCB0cmFuc2xhdGUgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuXG4gICAgICAgICAgICAgICAgQGlmIChlbWFpbD8ubm90Q29uZmlybWVkKSB7XG4gICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxpb24tZ3JpZCBjbGFzcz1cImlvbi1uby1wYWRkaW5nIGlvbi1wYWRkaW5nLWJvdHRvbVwiPlxuICAgICAgICAgICAgICAgICAgICAgIDxpb24tcm93PlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1jb2wgY29sb3I9XCJkYW5nZXJcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIHNsb3Q9XCJzdGFydFwiIGNvbG9yPVwiZGFuZ2VyXCIgbmFtZT1cImFsZXJ0LWNpcmNsZVwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDxpb24tdGV4dCBbaW5uZXJIVE1MXT1cIidBQ0NPVU5ULkVNQUlMX05PVF9DT05GSVJNRURfTEFCRUwnIHwgdHJhbnNsYXRlXCI+PC9pb24tdGV4dD5cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1yb3c+XG5cbiAgICAgICAgICAgICAgICAgICAgICA8aW9uLXJvdyBzdHlsZT1cImhlaWdodDogNTFweFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1jb2wgc3R5bGU9XCJ0ZXh0LWFsaWduOiByaWdodFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLXRleHQ+XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPHNtYWxsIFtpbm5lckhUTUxdPVwiJ0FDQ09VTlQuRU1BSUxfTk9UX1JFQ0VJVkVEX1FVRVNUSU9OJyB8IHRyYW5zbGF0ZVwiPjwvc21hbGw+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLXRleHQ+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1jb2w+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWNvbCBzaXplPVwiYXV0b1wiPlxuICAgICAgICAgICAgICAgICAgICAgICAgICBAaWYgKCFlbWFpbC5zZW5kaW5nKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1idXR0b24gZmlsbD1cInNvbGlkXCIgY29sb3I9XCJzZWNvbmRhcnlcIiAoY2xpY2spPVwic2VuZENvbmZpcm1hdGlvbkVtYWlsKCRldmVudClcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHt7ICdBQ0NPVU5ULkJUTl9SRVNFTkQnIHwgdHJhbnNsYXRlIH19XG4gICAgICAgICAgICAgICAgICAgICAgICAgICAgPC9pb24tYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgICAgICB9IEBlbHNlIHtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgICA8aW9uLXNwaW5uZXIgY2xhc3M9XCJpb24tbm8tcGFkZGluZ1wiPjwvaW9uLXNwaW5uZXI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvaW9uLWNvbD5cbiAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1yb3c+XG5cbiAgICAgICAgICAgICAgICAgICAgICA8aW9uLXJvdyAqbmdJZj1cImVtYWlsLmVycm9yICYmICFlbWFpbC5zZW5kaW5nXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW9uLWNvbD5cbiAgICAgICAgICAgICAgICAgICAgICAgICAgPHNwYW4gKm5nSWY9XCJlbWFpbC5lcnJvciAmJiAhZW1haWwuc2VuZGluZ1wiIFtpbm5lckhUTUxdPVwiZW1haWwuZXJyb3IgfCB0cmFuc2xhdGVcIj48L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgICAgICA8L2lvbi1jb2w+XG4gICAgICAgICAgICAgICAgICAgICAgPC9pb24tcm93PlxuICAgICAgICAgICAgICAgICAgICA8L2lvbi1ncmlkPlxuICAgICAgICAgICAgICAgICAgPC9pb24taXRlbT5cbiAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgPCEtLSBMYXN0IG5hbWUgLS0+XG4gICAgICAgICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdVU0VSLkxBU1RfTkFNRScgfCB0cmFuc2xhdGUgfX08L21hdC1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgPGlucHV0XG4gICAgICAgICAgICAgICAgICAgICAgbWF0SW5wdXRcbiAgICAgICAgICAgICAgICAgICAgICBbYXBwQXV0b2ZvY3VzXT1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgIFthdXRvZm9jdXNEZWxheV09XCI1MDBcIlxuICAgICAgICAgICAgICAgICAgICAgIGZvcm1Db250cm9sTmFtZT1cImxhc3ROYW1lXCJcbiAgICAgICAgICAgICAgICAgICAgICBhdXRvY29tcGxldGU9XCJzZWN0aW9uLWJsdWUgZmFtaWx5LW5hbWVcIlxuICAgICAgICAgICAgICAgICAgICAgIHJlcXVpcmVkXG4gICAgICAgICAgICAgICAgICAgIC8+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImZvcm0uY29udHJvbHMubGFzdE5hbWUuaGFzRXJyb3IoJ3JlcXVpcmVkJykgJiYgZm9ybS5jb250cm9scy5sYXN0TmFtZS5kaXJ0eVwiXG4gICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgICAgID5cbiAgICAgICAgICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1lcnJvciAqbmdJZj1cImZvcm0uY29udHJvbHMubGFzdE5hbWUuaGFzRXJyb3IoJ21pbmxlbmd0aCcpICYmIGZvcm0uY29udHJvbHMubGFzdE5hbWUuZGlydHlcIj5cbiAgICAgICAgICAgICAgICAgICAgICA8c3Bhbj57eyAnRVJST1IuRklFTERfTUlOX0xFTkdUSCcgfCB0cmFuc2xhdGU6IHsgcmVxdWlyZWRMZW5ndGg6IDIgfSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG5cbiAgICAgICAgICAgICAgICA8IS0tIEZpcnN0IG5hbWUgLS0+XG4gICAgICAgICAgICAgICAgPGlvbi1pdGVtIGxpbmVzPVwibm9uZVwiPlxuICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdVU0VSLkZJUlNUX05BTUUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgIDxpbnB1dCBtYXRJbnB1dCBmb3JtQ29udHJvbE5hbWU9XCJmaXJzdE5hbWVcIiBhdXRvY29tcGxldGU9XCJzZWN0aW9uLWJsdWUgZ2l2ZW4tbmFtZVwiIHJlcXVpcmVkIC8+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAqbmdJZj1cImZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIGZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCJcbiAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ21pbmxlbmd0aCcpICYmIGZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgJ0VSUk9SLkZJRUxEX01JTl9MRU5HVEgnIHwgdHJhbnNsYXRlOiB7IHJlcXVpcmVkTGVuZ3RoOiAyIH0gfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuXG4gICAgICAgICAgICAgICAgPCEtLSBBZGRpdGlvbmFsIGZpZWxkcyAtLT5cbiAgICAgICAgICAgICAgICBAZm9yIChkZWZpbml0aW9uIG9mIGFkZGl0aW9uYWxGaWVsZHM7IHRyYWNrIGRlZmluaXRpb24ua2V5KSB7XG4gICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxhcHAtZm9ybS1maWVsZFxuICAgICAgICAgICAgICAgICAgICAgIFtkZWZpbml0aW9uXT1cImRlZmluaXRpb25cIlxuICAgICAgICAgICAgICAgICAgICAgIFtmb3JtQ29udHJvbE5hbWVdPVwiZGVmaW5pdGlvbi5rZXlcIlxuICAgICAgICAgICAgICAgICAgICAgIFtyZXF1aXJlZF09XCJcbiAgICAgICAgICAgICAgICAgICAgICAgIChkZWZpbml0aW9uLmV4dHJhICYmIGRlZmluaXRpb24uZXh0cmEuYWNjb3VudCAmJiBkZWZpbml0aW9uLmV4dHJhLmFjY291bnQucmVxdWlyZWQpIHx8IGZhbHNlXG4gICAgICAgICAgICAgICAgICAgICAgXCJcbiAgICAgICAgICAgICAgICAgICAgPjwvYXBwLWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgICAgICA8L2lvbi1pdGVtPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9pb24tbGlzdD5cblxuICAgICAgICAgICAgICA8IS0tIFNlY3VyaXR5IC0tPlxuICAgICAgICAgICAgICBAaWYgKHNob3dTZWN1cml0eURldGFpbHMpIHtcbiAgICAgICAgICAgICAgICA8aW9uLWxpc3QtaGVhZGVyPjxoMyB0cmFuc2xhdGU+QUNDT1VOVC5TRUNVUklUWS5USVRMRTwvaDM+PC9pb24tbGlzdC1oZWFkZXI+XG5cbiAgICAgICAgICAgICAgICA8aW9uLWxpc3QgW2luc2V0XT1cIm1vYmlsZVwiPlxuICAgICAgICAgICAgICAgICAgPGlvbi1pdGVtXG4gICAgICAgICAgICAgICAgICAgIFtidXR0b25dPVwibW9iaWxlXCJcbiAgICAgICAgICAgICAgICAgICAgcm91dGVyRGlyZWN0aW9uPVwiZm9yd2FyZFwiXG4gICAgICAgICAgICAgICAgICAgIGxpbmVzPVwibm9uZVwiXG4gICAgICAgICAgICAgICAgICAgIChjbGljayk9XCJvcGVuQ2hhbmdlUGFzc3dvcmRQYWdlKClcIlxuICAgICAgICAgICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICBAaWYgKCFtb2JpbGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8aW9uLWljb24gc2xvdD1cInN0YXJ0XCIgbmFtZT1cImtleXBhZFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgICAgPGlvbi1sYWJlbD57eyAnQUNDT1VOVC5TRUNVUklUWS5QQVNTV09SRCcgfCB0cmFuc2xhdGUgfX08L2lvbi1sYWJlbD5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICA8aW9uLXRleHQgY29sb3I9XCJ0ZXJ0aWFyeVwiPnt7ICdBQ0NPVU5ULlNFQ1VSSVRZLkJUTl9DSEFOR0VfUEFTU1dPUkQnIHwgdHJhbnNsYXRlIH19PC9pb24tdGV4dD5cbiAgICAgICAgICAgICAgICAgICAgQGlmICghbW9iaWxlKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uIHNsb3Q9XCJlbmRcIiBjb2xvcj1cInRlcnRpYXJ5XCIgbmFtZT1cImNoZXZyb24tZm9yd2FyZFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgICAgICAgPC9pb24tbGlzdD5cbiAgICAgICAgICAgICAgfVxuXG4gICAgICAgICAgICAgIDwhLS0gVGVjaG5pY2FsIGRldGFpbHMgLS0+XG4gICAgICAgICAgICAgIEBpZiAoc2hvd1RlY2huaWNhbERldGFpbHMpIHtcbiAgICAgICAgICAgICAgICA8aW9uLWxpc3QtaGVhZGVyPjxoMyB0cmFuc2xhdGU+QUNDT1VOVC5VU0VSX0RFVEFJTFMuVEVDSE5JQ0FMX0RJVklERVI8L2gzPjwvaW9uLWxpc3QtaGVhZGVyPlxuXG4gICAgICAgICAgICAgICAgPGlvbi1saXN0IFtpbnNldF09XCJtb2JpbGVcIj5cbiAgICAgICAgICAgICAgICAgIDwhLS0gcHJvZmlsZSAtLT5cbiAgICAgICAgICAgICAgICAgIDxpb24taXRlbSBsaW5lcz1cIm5vbmVcIj5cbiAgICAgICAgICAgICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ0FDQ09VTlQuVVNFUl9ERVRBSUxTLlBST0ZJTEUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IGhpZGRlbiByZWFkb25seT1cInRydWVcIiBmb3JtQ29udHJvbE5hbWU9XCJtYWluUHJvZmlsZVwiIHJlcXVpcmVkIC8+XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4+e3sgJ1VTRVIuUFJPRklMRV9FTlVNLicgKyBmb3JtLmNvbnRyb2xzLm1haW5Qcm9maWxlLnZhbHVlIHwgdHJhbnNsYXRlIH19PC9zcGFuPlxuICAgICAgICAgICAgICAgICAgICAgIDxtYXQtZXJyb3JcbiAgICAgICAgICAgICAgICAgICAgICAgICpuZ0lmPVwiZm9ybS5jb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ21haW5Qcm9maWxlJykgJiYgZm9ybS5jb250cm9scy5tYWluUHJvZmlsZS5kaXJ0eVwiXG4gICAgICAgICAgICAgICAgICAgICAgICB0cmFuc2xhdGVcbiAgICAgICAgICAgICAgICAgICAgICA+XG4gICAgICAgICAgICAgICAgICAgICAgICBFUlJPUi5GSUVMRF9SRVFVSVJFRFxuICAgICAgICAgICAgICAgICAgICAgIDwvbWF0LWVycm9yPlxuICAgICAgICAgICAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgICAgICAgPC9pb24taXRlbT5cblxuICAgICAgICAgICAgICAgICAgPCEtLSBwdWJrZXkgLS0+XG4gICAgICAgICAgICAgICAgICA8aW9uLWl0ZW0gbGluZXM9XCJub25lXCI+XG4gICAgICAgICAgICAgICAgICAgIDxtYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWxhYmVsPnt7ICdBQ0NPVU5ULlVTRVJfREVUQUlMUy5QVUJLRVknIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICAgICAgICAgICAgPGlucHV0IG1hdElucHV0IHJlYWRvbmx5PVwidHJ1ZVwiIGZvcm1Db250cm9sTmFtZT1cInB1YmtleVwiIHJlcXVpcmVkIC8+XG4gICAgICAgICAgICAgICAgICAgICAgPG1hdC1lcnJvclxuICAgICAgICAgICAgICAgICAgICAgICAgKm5nSWY9XCJmb3JtLmNvbnRyb2xzLmZpcnN0TmFtZS5oYXNFcnJvcigncHVia2V5JykgJiYgZm9ybS5jb250cm9scy5maXJzdE5hbWUuZGlydHlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICAgICAgICAgICAgPlxuICAgICAgICAgICAgICAgICAgICAgICAgRVJST1IuRklFTERfUkVRVUlSRURcbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgICA8bWF0LWVycm9yICpuZ0lmPVwiZm9ybS5jb250cm9scy5maXJzdE5hbWUuaGFzRXJyb3IoJ3B1YmtleScpICYmIGZvcm0uY29udHJvbHMuZmlyc3ROYW1lLmRpcnR5XCI+XG4gICAgICAgICAgICAgICAgICAgICAgICA8c3BhbiB0cmFuc2xhdGU+RVJST1IuRklFTERfTk9UX1ZBTElEX1BVQktFWTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICAgICAgICAgICAgPC9tYXQtZm9ybS1maWVsZD5cbiAgICAgICAgICAgICAgICAgIDwvaW9uLWl0ZW0+XG4gICAgICAgICAgICAgICAgPC9pb24tbGlzdD5cbiAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgPC9pb24tY29sPlxuXG4gICAgICAgICAgICA8IS0tIHJpZ2h0IG1hcmdpbiAtLT5cbiAgICAgICAgICAgIDxpb24tY29sIHNpemU9XCIwXCIgc2l6ZS1sZz1cIjFcIiBzaXplLXhsPVwiMlwiPiZuYnNwOzwvaW9uLWNvbD5cbiAgICAgICAgICA8L2lvbi1yb3c+XG4gICAgICAgIDwvaW9uLWdyaWQ+XG4gICAgICA8L21hdC10YWI+XG5cbiAgICAgIDwhLS0gVEFCOiBzZXR0aW5ncyAtLT5cbiAgICAgIDxtYXQtdGFiIFtsYWJlbF09XCInQUNDT1VOVC5TRVRUSU5HUy5USVRMRScgfCB0cmFuc2xhdGVcIiBmb3JtR3JvdXBOYW1lPVwic2V0dGluZ3NcIj5cbiAgICAgICAgPG5nLXRlbXBsYXRlIG1hdC10YWItbGFiZWw+XG4gICAgICAgICAgPG1hdC1pY29uPlxuICAgICAgICAgICAgPGlvbi1pY29uIG1hdFByZWZpeCBzbG90PVwic3RhcnRcIiBuYW1lPVwic2V0dGluZ3NcIj48L2lvbi1pY29uPlxuICAgICAgICAgIDwvbWF0LWljb24+XG4gICAgICAgICAgPGlvbi1sYWJlbCB0cmFuc2xhdGU+QUNDT1VOVC5TRVRUSU5HUy5USVRMRTwvaW9uLWxhYmVsPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpb24tcGFkZGluZ1wiPlxuICAgICAgICAgIDxwIFtpbm5lckhUTUxdPVwiJ0FDQ09VTlQuU0VUVElOR1MuREVTQ1JJUFRJT04nIHwgdHJhbnNsYXRlXCI+PC9wPlxuXG4gICAgICAgICAgPG1hdC1mb3JtLWZpZWxkPlxuICAgICAgICAgICAgPG1hdC1sYWJlbD57eyAnQUNDT1VOVC5TRVRUSU5HUy5MT0NBTEUnIHwgdHJhbnNsYXRlIH19PC9tYXQtbGFiZWw+XG4gICAgICAgICAgICA8bWF0LXNlbGVjdCBmb3JtQ29udHJvbE5hbWU9XCJsb2NhbGVcIiByZXF1aXJlZD5cbiAgICAgICAgICAgICAgPG1hdC1vcHRpb24gKm5nRm9yPVwibGV0IGl0ZW0gb2YgbG9jYWxlc1wiIFt2YWx1ZV09XCJpdGVtLmtleVwiPlxuICAgICAgICAgICAgICAgIHt7IGl0ZW0udmFsdWUgfX1cbiAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgPG1hdC1lcnJvclxuICAgICAgICAgICAgICAqbmdJZj1cInNldHRpbmdzRm9ybT8uY29udHJvbHMubG9jYWxlLmhhc0Vycm9yKCdyZXF1aXJlZCcpICYmIHNldHRpbmdzRm9ybT8uY29udHJvbHMubG9jYWxlLmRpcnR5XCJcbiAgICAgICAgICAgICAgdHJhbnNsYXRlXG4gICAgICAgICAgICA+XG4gICAgICAgICAgICAgIEVSUk9SLkZJRUxEX1JFUVVJUkVEXG4gICAgICAgICAgICA8L21hdC1lcnJvcj5cbiAgICAgICAgICA8L21hdC1mb3JtLWZpZWxkPlxuXG4gICAgICAgICAgPCEtLSBsYXQvbG9uZyBmb3JtYXQtLT5cbiAgICAgICAgICBAaWYgKHNob3dMYXRMb25Gb3JtYXQpIHtcbiAgICAgICAgICAgIEBsZXQgY29udHJvbCA9IHNldHRpbmdzRm9ybSB8IGZvcm1HZXRDb250cm9sOiAnbGF0TG9uZ0Zvcm1hdCc7XG4gICAgICAgICAgICA8bWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgICAgIDxtYXQtbGFiZWw+e3sgJ0FDQ09VTlQuU0VUVElOR1MuTEFUX0xPTkdfRk9STUFUJyB8IHRyYW5zbGF0ZSB9fTwvbWF0LWxhYmVsPlxuICAgICAgICAgICAgICA8bWF0LXNlbGVjdCBbZm9ybUNvbnRyb2xdPVwiY29udHJvbFwiIHJlcXVpcmVkPlxuICAgICAgICAgICAgICAgIEBmb3IgKGl0ZW0gb2YgbGF0TG9uZ0Zvcm1hdHM7IHRyYWNrIGl0ZW0pIHtcbiAgICAgICAgICAgICAgICAgIDxtYXQtb3B0aW9uIFt2YWx1ZV09XCJpdGVtXCI+XG4gICAgICAgICAgICAgICAgICAgIHt7ICdDT01NT04uTEFUX0xPTkcuRU5VTS4nICsgaXRlbSB8IHVwcGVyY2FzZSB8IHRyYW5zbGF0ZSB9fVxuICAgICAgICAgICAgICAgICAgPC9tYXQtb3B0aW9uPlxuICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgPC9tYXQtc2VsZWN0PlxuICAgICAgICAgICAgICBAaWYgKGNvbnRyb2wuZGlydHkgJiYgY29udHJvbC5oYXNFcnJvcigncmVxdWlyZWQnKSkge1xuICAgICAgICAgICAgICAgIDxtYXQtZXJyb3IgdHJhbnNsYXRlPkVSUk9SLkZJRUxEX1JFUVVJUkVEPC9tYXQtZXJyb3I+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvbWF0LWZvcm0tZmllbGQ+XG4gICAgICAgICAgfVxuICAgICAgICA8L2Rpdj5cblxuICAgICAgICA8IS0tIE9wdGlvbnMgdGFibGUgLS0+XG4gICAgICAgIDxkaXYgY2xhc3M9XCJvcHRpb25zLXRhYmxlXCIgW2NsYXNzLmNkay12aXN1YWxseS1oaWRkZW5dPVwib3B0aW9uRGVmaW5pdGlvbnMgfCBpc0VtcHR5QXJyYXlcIj5cbiAgICAgICAgICA8YXBwLXByb3BlcnRpZXMtdGFibGVcbiAgICAgICAgICAgICNwcm9wZXJ0aWVzVGFibGVcbiAgICAgICAgICAgIGkxOG5Db2x1bW5QcmVmaXg9XCJBQ0NPVU5ULlNFVFRJTkdTLk9QVElPTlMuXCJcbiAgICAgICAgICAgIFtkZWZpbml0aW9uc109XCJvcHRpb25EZWZpbml0aW9uc1wiXG4gICAgICAgICAgICBbZGlzYWJsZWRdPVwiZGlzYWJsZWRcIlxuICAgICAgICAgICAgW2NhbkVkaXRdPVwidHJ1ZVwiXG4gICAgICAgICAgICBbZGVidWddPVwiZGVidWdcIlxuICAgICAgICAgICAgKG9uRGlydHkpPVwiJGV2ZW50ID8gbWFya0FzRGlydHkoKSA6IHVuZGVmaW5lZFwiXG4gICAgICAgICAgPjwvYXBwLXByb3BlcnRpZXMtdGFibGU+XG4gICAgICAgIDwvZGl2PlxuICAgICAgPC9tYXQtdGFiPlxuXG4gICAgICA8IS0tIFRBQjogdG9rZW5zIC0tPlxuICAgICAgPG1hdC10YWIgW2xhYmVsXT1cIidBQ0NPVU5ULlRPS0VOUy5USVRMRScgfCB0cmFuc2xhdGVcIiBmb3JtR3JvdXBOYW1lPVwidG9rZW5zXCIgW2Rpc2FibGVkXT1cIiFzaG93QXBpVG9rZW5zXCI+XG4gICAgICAgIDxuZy10ZW1wbGF0ZSBtYXQtdGFiLWxhYmVsPlxuICAgICAgICAgIDxtYXQtaWNvbj5cbiAgICAgICAgICAgIDxpb24taWNvbiBtYXRQcmVmaXggc2xvdD1cInN0YXJ0XCIgbmFtZT1cInRpY2tldFwiPjwvaW9uLWljb24+XG4gICAgICAgICAgPC9tYXQtaWNvbj5cbiAgICAgICAgICA8aW9uLWxhYmVsIHRyYW5zbGF0ZT5BQ0NPVU5ULlRPS0VOUy5USVRMRTwvaW9uLWxhYmVsPlxuICAgICAgICA8L25nLXRlbXBsYXRlPlxuXG4gICAgICAgIDxkaXYgY2xhc3M9XCJpb24tcGFkZGluZ1wiPlxuICAgICAgICAgIDxwIFtpbm5lckhUTUxdPVwiJ0FDQ09VTlQuVE9LRU5TLkRFU0NSSVBUSU9OJyB8IHRyYW5zbGF0ZVwiPjwvcD5cbiAgICAgICAgPC9kaXY+XG4gICAgICAgIDwhLS0gVG9rZW5zIHRhYmxlIC0tPlxuICAgICAgICA8ZGl2IGNsYXNzPVwidG9rZW5zLXRhYmxlXCI+XG4gICAgICAgICAgPGFwcC11c2VyLXRva2VuLXRhYmxlXG4gICAgICAgICAgICAjdG9rZW5zVGFibGVcbiAgICAgICAgICAgIFtkaXNhYmxlZF09XCJkaXNhYmxlZFwiXG4gICAgICAgICAgICBbY2FuRWRpdF09XCJ0cnVlXCJcbiAgICAgICAgICAgIFtkZWJ1Z109XCJkZWJ1Z1wiXG4gICAgICAgICAgICAob25EaXJ0eSk9XCIkZXZlbnQgPyBtYXJrQXNEaXJ0eSgpIDogdW5kZWZpbmVkXCJcbiAgICAgICAgICA+PC9hcHAtdXNlci10b2tlbi10YWJsZT5cbiAgICAgICAgPC9kaXY+XG4gICAgICA8L21hdC10YWI+XG4gICAgPC9tYXQtdGFiLWdyb3VwPlxuICA8L2Zvcm0+XG48L2lvbi1jb250ZW50PlxuXG48aW9uLWZvb3RlciBoaWRkZW4teHMgaGlkZGVuLXNtIGhpZGRlbi1tb2JpbGU+XG4gIDxhcHAtZm9ybS1idXR0b25zLWJhciAob25DYW5jZWwpPVwiY2FuY2VsKClcIiAob25TYXZlKT1cInNhdmUoKVwiIFtkaXNhYmxlZF09XCIhZm9ybS5kaXJ0eSB8fCAhdmFsaWQgfHwgc2F2aW5nXCI+XG4gICAgPCEtLSBlcnJvciAtLT5cbiAgICA8aW9uLWl0ZW0gKm5nSWY9XCJlcnJvciAmJiAhbW9iaWxlXCIgbGluZXM9XCJub25lXCI+XG4gICAgICA8aW9uLWljb24gY29sb3I9XCJkYW5nZXJcIiBzbG90PVwic3RhcnRcIiBuYW1lPVwiYWxlcnQtY2lyY2xlXCI+PC9pb24taWNvbj5cbiAgICAgIDxpb24tbGFiZWwgY29sb3I9XCJkYW5nZXJcIiBjbGFzcz1cImVycm9yXCIgW2lubmVySFRNTF09XCJlcnJvciB8IHRyYW5zbGF0ZVwiPjwvaW9uLWxhYmVsPlxuICAgIDwvaW9uLWl0ZW0+XG4gIDwvYXBwLWZvcm0tYnV0dG9ucy1iYXI+XG48L2lvbi1mb290ZXI+XG4iXX0=
|