valtech-components 2.0.992 → 2.0.993
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/esm2022/lib/components/molecules/comment/comment.component.mjs +3 -3
- package/esm2022/lib/components/organisms/notifications-view/notifications-view.component.mjs +736 -0
- package/esm2022/lib/components/organisms/notifications-view/notifications-view.i18n.mjs +76 -0
- package/esm2022/lib/components/organisms/notifications-view/notifications.routes.mjs +32 -0
- package/esm2022/lib/components/organisms/notifications-view/types.mjs +2 -0
- package/esm2022/lib/components/organisms/profile-view/profile-view.component.mjs +16 -6
- package/esm2022/lib/services/preferences/preferences.service.mjs +1 -10
- package/esm2022/lib/version.mjs +2 -2
- package/esm2022/public-api.mjs +4 -1
- package/fesm2022/valtech-components.mjs +999 -180
- package/fesm2022/valtech-components.mjs.map +1 -1
- package/lib/components/organisms/notifications-view/notifications-view.component.d.ts +168 -0
- package/lib/components/organisms/notifications-view/notifications-view.i18n.d.ts +9 -0
- package/lib/components/organisms/notifications-view/notifications.routes.d.ts +27 -0
- package/lib/components/organisms/notifications-view/types.d.ts +52 -0
- package/lib/version.d.ts +1 -1
- package/package.json +1 -1
- package/public-api.d.ts +3 -0
|
@@ -0,0 +1,736 @@
|
|
|
1
|
+
import { Component, computed, effect, inject, Input, signal } from '@angular/core';
|
|
2
|
+
import { ActivatedRoute } from '@angular/router';
|
|
3
|
+
import { IonIcon } from '@ionic/angular/standalone';
|
|
4
|
+
import { addIcons } from 'ionicons';
|
|
5
|
+
import { alarmOutline, chatboxEllipsesOutline, chatbubbleOutline, checkmarkCircleOutline, checkmarkDoneOutline, cloudOfflineOutline, cogOutline, documentTextOutline, notificationsOffOutline, notificationsOutline, openOutline, personOutline, } from 'ionicons/icons';
|
|
6
|
+
import { ButtonComponent } from '../../atoms/button/button.component';
|
|
7
|
+
import { DisplayComponent } from '../../atoms/display/display.component';
|
|
8
|
+
import { TextComponent } from '../../atoms/text/text.component';
|
|
9
|
+
import { TitleComponent } from '../../atoms/title/title.component';
|
|
10
|
+
import { EmptyStateComponent } from '../../molecules/empty-state/empty-state.component';
|
|
11
|
+
import { createErrorStateProps } from '../../molecules/empty-state/factory';
|
|
12
|
+
import { SkeletonLayoutComponent } from '../skeleton-layout/skeleton-layout.component';
|
|
13
|
+
import { ComponentStates } from '../../types';
|
|
14
|
+
import { AuthService } from '../../../services/auth/auth.service';
|
|
15
|
+
import { NotificationActionService } from '../../../services/auth/notification-action.service';
|
|
16
|
+
import { I18nService } from '../../../services/i18n';
|
|
17
|
+
import { interpretError } from '../../../services/errors/interpret-error';
|
|
18
|
+
import { NavigationService } from '../../../services/navigation/navigation.service';
|
|
19
|
+
import { NotificationsService } from '../../../services/firebase/notifications.service';
|
|
20
|
+
import { PageRefreshService } from '../../../services/page-refresh/page-refresh.service';
|
|
21
|
+
import { createRefreshableStream } from '../../../services/refreshable-stream/refreshable-stream';
|
|
22
|
+
import { ToastService } from '../../../services/toast.service';
|
|
23
|
+
import { ValtechErrorService } from '../../../services/errors/valtech-error.service';
|
|
24
|
+
import { NOTIFICATIONS_VIEW_I18N } from './notifications-view.i18n';
|
|
25
|
+
import * as i0 from "@angular/core";
|
|
26
|
+
addIcons({
|
|
27
|
+
alarmOutline,
|
|
28
|
+
chatboxEllipsesOutline,
|
|
29
|
+
chatbubbleOutline,
|
|
30
|
+
checkmarkCircleOutline,
|
|
31
|
+
checkmarkDoneOutline,
|
|
32
|
+
cloudOfflineOutline,
|
|
33
|
+
cogOutline,
|
|
34
|
+
documentTextOutline,
|
|
35
|
+
notificationsOffOutline,
|
|
36
|
+
notificationsOutline,
|
|
37
|
+
openOutline,
|
|
38
|
+
personOutline,
|
|
39
|
+
});
|
|
40
|
+
const DEFAULT_NAMESPACE = 'Notifications';
|
|
41
|
+
const DEFAULT_SETTINGS_PATH = '/app/settings/notifications';
|
|
42
|
+
const DEFAULT_PAGE_SIZE = 10;
|
|
43
|
+
const DEFAULT_MAX_LOAD = 50;
|
|
44
|
+
/**
|
|
45
|
+
* `val-notifications-view` — inbox de notificaciones full-feature autocontenido
|
|
46
|
+
* (organism). Promovido desde `showcase` bajo el proceso de ADR-021.
|
|
47
|
+
*
|
|
48
|
+
* Separado de `/app/settings/notifications` (que controla permiso FCM + master
|
|
49
|
+
* toggle). Aquí el user lee/abre/marca-leídas sus mensajes.
|
|
50
|
+
*
|
|
51
|
+
* - **Stream real-time** vía `NotificationsService.getAll(maxLoad)` envuelto en
|
|
52
|
+
* `createRefreshableStream` (gateado por `firebaseAuthReady`, retry corto,
|
|
53
|
+
* `firstEmitTimeoutMs: 15000`). Estados: loading (skeleton), error
|
|
54
|
+
* (`val-empty-state` + reintentar), empty (`val-empty-state` + CTA), data
|
|
55
|
+
* (lista agrupada Hoy / Este mes / Anteriores).
|
|
56
|
+
* - **Abrir** una notif → `NotificationActionService.open()` (markRead +
|
|
57
|
+
* switch-org + navegar/handoff cross-app). Hook `onNotificationOpen` opcional.
|
|
58
|
+
* - **Marcar todas como leídas** (gateado por `enableMarkAll`).
|
|
59
|
+
* - **CTA push-off** cuando el permiso del navegador no está concedido (gateado
|
|
60
|
+
* por `showPushOffCta`); navega a `settingsNotificationsPath`.
|
|
61
|
+
* - **Paginación soft** — slice local (`pageSize`, +`pageSize` por click) sobre el
|
|
62
|
+
* cache del stream; el tope de fetch es `maxLoad`.
|
|
63
|
+
* - **i18n auto-registrado** es/en bajo `i18nNamespace` (default `Notifications`).
|
|
64
|
+
*
|
|
65
|
+
* NO renderiza ion-content — vive dentro de val-page-wrapper. `Router` y
|
|
66
|
+
* `ActivatedRoute` se inyectan `{ optional: true }` → funciona sin router
|
|
67
|
+
* (embebida / Storybook). El forward-compat icon resolver lee `notif.payload.icon`
|
|
68
|
+
* si existe (`{ type, value, color? }`), cae a un mapa por `notif.type`, luego a
|
|
69
|
+
* `notifications-outline`.
|
|
70
|
+
*/
|
|
71
|
+
export class NotificationsViewComponent {
|
|
72
|
+
/** Namespace i18n resuelto (capturado para llamadas no-reactivas). */
|
|
73
|
+
get ns() {
|
|
74
|
+
return this.resolvedConfig().i18nNamespace;
|
|
75
|
+
}
|
|
76
|
+
/** Paso de paginación soft (revela +N por "cargar más"). */
|
|
77
|
+
get pageStep() {
|
|
78
|
+
return this.resolvedConfig().pageSize;
|
|
79
|
+
}
|
|
80
|
+
constructor() {
|
|
81
|
+
this.nav = inject(NavigationService);
|
|
82
|
+
this.i18n = inject(I18nService);
|
|
83
|
+
this.notifs = inject(NotificationsService);
|
|
84
|
+
this.action = inject(NotificationActionService);
|
|
85
|
+
this.toast = inject(ToastService);
|
|
86
|
+
this.errors = inject(ValtechErrorService);
|
|
87
|
+
this.auth = inject(AuthService);
|
|
88
|
+
this.pageRefresh = inject(PageRefreshService);
|
|
89
|
+
// `ActivatedRoute` opcional → la vista funciona embebida / en Storybook sin
|
|
90
|
+
// router (solo lo usa para leer el route data de config como fallback). La
|
|
91
|
+
// navegación va por `NavigationService` (wrapper opcional sobre `Router`).
|
|
92
|
+
this.route = inject(ActivatedRoute, { optional: true });
|
|
93
|
+
this.resolvedConfig = computed(() => {
|
|
94
|
+
const fromRoute = (this.route?.snapshot.data['notificationsConfig'] ?? {});
|
|
95
|
+
const merged = { ...fromRoute, ...(this.config ?? {}) };
|
|
96
|
+
return {
|
|
97
|
+
showPushOffCta: merged.showPushOffCta ?? true,
|
|
98
|
+
enableMarkAll: merged.enableMarkAll ?? true,
|
|
99
|
+
settingsNotificationsPath: merged.settingsNotificationsPath ?? DEFAULT_SETTINGS_PATH,
|
|
100
|
+
i18nNamespace: merged.i18nNamespace ?? DEFAULT_NAMESPACE,
|
|
101
|
+
pageSize: merged.pageSize ?? DEFAULT_PAGE_SIZE,
|
|
102
|
+
maxLoad: merged.maxLoad ?? DEFAULT_MAX_LOAD,
|
|
103
|
+
onNotificationOpen: merged.onNotificationOpen,
|
|
104
|
+
};
|
|
105
|
+
});
|
|
106
|
+
this._expanded = signal(new Set());
|
|
107
|
+
this._pageSize = signal(this.resolvedConfig().pageSize);
|
|
108
|
+
this._bulkBusy = signal(false);
|
|
109
|
+
this._loadingMore = signal(false);
|
|
110
|
+
/**
|
|
111
|
+
* Push activado = permiso del navegador en `granted`. Si NO está activado,
|
|
112
|
+
* el user puede leer el inbox (Firestore) pero NO recibirá push en su
|
|
113
|
+
* dispositivo → mostramos una card que lo invita a ir a configuración.
|
|
114
|
+
* Se evalúa en cada montaje de la vista.
|
|
115
|
+
*/
|
|
116
|
+
this.pushEnabled = signal(this.auth.getNotificationPermissionState() === 'granted');
|
|
117
|
+
/**
|
|
118
|
+
* Stream firestore real-time vía el helper estándar `createRefreshableStream`
|
|
119
|
+
* (modo real-time: factory devuelve un listener vivo `notifs.getAll(maxLoad)`).
|
|
120
|
+
*
|
|
121
|
+
* El helper gatea la primera suscripción por `firebaseAuthReady`, aplica un
|
|
122
|
+
* `retry` corto con backoff y, tras agotar reintentos, emite el fallback (`[]`)
|
|
123
|
+
* y marca `error` — estado de error en UI, no skeleton infinito. `reload()`
|
|
124
|
+
* re-suscribe el stream completo (lo usa el pull-to-refresh).
|
|
125
|
+
*/
|
|
126
|
+
this._stream = createRefreshableStream(() => this.notifs.getAll(this.resolvedConfig().maxLoad), {
|
|
127
|
+
fallback: [],
|
|
128
|
+
// `notifs.getAll()` YA gatea internamente por `firebaseAuthReady`. Si el
|
|
129
|
+
// stream también gateara, serían DOS esperas de auth apiladas.
|
|
130
|
+
gateOnFirebaseAuth: false,
|
|
131
|
+
// Cold start de PWA en iOS puede pasar de 8s en redes lentas; con 15s
|
|
132
|
+
// evitamos el falso estado de error.
|
|
133
|
+
firstEmitTimeoutMs: 15000,
|
|
134
|
+
});
|
|
135
|
+
/** True si el stream falló tras agotar reintentos → muestra estado de error. */
|
|
136
|
+
this.streamError = this._stream.error;
|
|
137
|
+
this.loading = computed(() => this._stream.data() === null);
|
|
138
|
+
/**
|
|
139
|
+
* Notifs reales mostradas. Filtramos docs sin título Y sin body — son ruido
|
|
140
|
+
* (típicamente sentinel/system writes pre-schema con title/body opcionales).
|
|
141
|
+
*/
|
|
142
|
+
this.allNotifs = computed(() => (this._stream.data() ?? []).filter(n => !!(n.title && n.title.trim()) || !!(n.body && n.body.trim())));
|
|
143
|
+
this.hasMore = computed(() => this.allNotifs().length > this._pageSize());
|
|
144
|
+
this.showMarkAll = computed(() => this.resolvedConfig().enableMarkAll && !this.loading() && this.allNotifs().some(n => !n.isRead));
|
|
145
|
+
/** Sub-conjunto paginado, agrupado por período. */
|
|
146
|
+
this.groups = computed(() => {
|
|
147
|
+
const items = this.allNotifs().slice(0, this._pageSize());
|
|
148
|
+
const now = new Date();
|
|
149
|
+
const buckets = {
|
|
150
|
+
today: [],
|
|
151
|
+
thisMonth: [],
|
|
152
|
+
earlier: [],
|
|
153
|
+
};
|
|
154
|
+
for (const n of items) {
|
|
155
|
+
buckets[this.bucketOf(n, now)].push(n);
|
|
156
|
+
}
|
|
157
|
+
const out = [];
|
|
158
|
+
if (buckets.today.length) {
|
|
159
|
+
out.push({ key: 'today', label: this.tt('groupToday'), items: buckets.today });
|
|
160
|
+
}
|
|
161
|
+
if (buckets.thisMonth.length) {
|
|
162
|
+
out.push({
|
|
163
|
+
key: 'thisMonth',
|
|
164
|
+
label: this.tt('groupThisMonth'),
|
|
165
|
+
items: buckets.thisMonth,
|
|
166
|
+
});
|
|
167
|
+
}
|
|
168
|
+
if (buckets.earlier.length) {
|
|
169
|
+
out.push({ key: 'earlier', label: this.tt('groupEarlier'), items: buckets.earlier });
|
|
170
|
+
}
|
|
171
|
+
return out;
|
|
172
|
+
});
|
|
173
|
+
this.pageTitle = computed(() => this.tt('pageTitle'));
|
|
174
|
+
this.pageDescription = computed(() => this.tt('pageDescription'));
|
|
175
|
+
// CTA "activa las notificaciones push" — visible cuando pushEnabled() es false.
|
|
176
|
+
this.ctaTitle = computed(() => this.tt('pushOffTitle'));
|
|
177
|
+
this.ctaHint = computed(() => this.tt('pushOffHint'));
|
|
178
|
+
this.ctaButtonProps = computed(() => ({
|
|
179
|
+
text: this.tt('pushOffCta'),
|
|
180
|
+
color: 'dark',
|
|
181
|
+
fill: 'outline',
|
|
182
|
+
size: 'small',
|
|
183
|
+
shape: 'round',
|
|
184
|
+
type: 'button',
|
|
185
|
+
}));
|
|
186
|
+
/**
|
|
187
|
+
* Estado de error de carga: convierte el error del stream en
|
|
188
|
+
* `EmptyStateMetadata` via el helper canónico `createErrorStateProps`.
|
|
189
|
+
* El helper decide variante (`offline` vs `error`) por `isNetwork`.
|
|
190
|
+
* Null cuando el stream no ha fallado.
|
|
191
|
+
*/
|
|
192
|
+
this.errorState = computed(() => {
|
|
193
|
+
this.i18n.lang();
|
|
194
|
+
const err = this.streamError();
|
|
195
|
+
if (!err)
|
|
196
|
+
return null;
|
|
197
|
+
return createErrorStateProps(err, {
|
|
198
|
+
title: {
|
|
199
|
+
offline: this.tt('offlineTitle'),
|
|
200
|
+
error: this.tt('loadErrorTitle'),
|
|
201
|
+
},
|
|
202
|
+
description: {
|
|
203
|
+
offline: this.tt('offlineHint'),
|
|
204
|
+
error: interpretError(err).message || this.tt('loadErrorHint'),
|
|
205
|
+
},
|
|
206
|
+
retryLabel: this.tt('retryCta'),
|
|
207
|
+
onRetry: () => this._stream.reload(),
|
|
208
|
+
retrying: this.loading(),
|
|
209
|
+
});
|
|
210
|
+
});
|
|
211
|
+
/**
|
|
212
|
+
* Estado vacío (lista real = 0 notificaciones, sin error de carga).
|
|
213
|
+
* Se construye manualmente con `variant: 'empty'` — sin helper de error.
|
|
214
|
+
*/
|
|
215
|
+
this.emptyStateProps = computed(() => {
|
|
216
|
+
this.i18n.lang();
|
|
217
|
+
return {
|
|
218
|
+
variant: 'empty',
|
|
219
|
+
icon: 'notifications-off-outline',
|
|
220
|
+
title: this.tt('empty'),
|
|
221
|
+
description: this.tt('emptyHint'),
|
|
222
|
+
action: {
|
|
223
|
+
label: this.tt('emptyCta'),
|
|
224
|
+
handler: () => this.onGoToSettings(),
|
|
225
|
+
},
|
|
226
|
+
};
|
|
227
|
+
});
|
|
228
|
+
this.seeMore = computed(() => this.tt('seeMore'));
|
|
229
|
+
this.seeLess = computed(() => this.tt('seeLess'));
|
|
230
|
+
this.markAllButtonProps = computed(() => ({
|
|
231
|
+
text: this.tt('markAll'),
|
|
232
|
+
color: 'dark',
|
|
233
|
+
fill: 'outline',
|
|
234
|
+
size: 'small',
|
|
235
|
+
shape: 'round',
|
|
236
|
+
type: 'button',
|
|
237
|
+
icon: { name: 'checkmark-done-outline', slot: 'start' },
|
|
238
|
+
state: this._bulkBusy() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
239
|
+
}));
|
|
240
|
+
this.loadMoreButtonProps = computed(() => ({
|
|
241
|
+
text: this.tt('loadMore'),
|
|
242
|
+
color: 'dark',
|
|
243
|
+
fill: 'clear',
|
|
244
|
+
size: 'default',
|
|
245
|
+
shape: 'round',
|
|
246
|
+
type: 'button',
|
|
247
|
+
state: this._loadingMore() ? ComponentStates.WORKING : ComponentStates.ENABLED,
|
|
248
|
+
}));
|
|
249
|
+
const ns = this.ns;
|
|
250
|
+
if (!this.i18n.hasNamespace(ns)) {
|
|
251
|
+
this.i18n.registerContent(ns, NOTIFICATIONS_VIEW_I18N);
|
|
252
|
+
}
|
|
253
|
+
this.nav.setBackHeader('pageTitle', ns, { withMenu: true });
|
|
254
|
+
// Re-aplicar header en cambio de idioma.
|
|
255
|
+
effect(() => {
|
|
256
|
+
this.i18n.lang();
|
|
257
|
+
this.nav.setBackHeader('pageTitle', this.ns, { withMenu: true });
|
|
258
|
+
}, { allowSignalWrites: true });
|
|
259
|
+
}
|
|
260
|
+
/**
|
|
261
|
+
* Registra el pull-to-refresh estándar. Usamos `ngOnInit`/`ngOnDestroy`
|
|
262
|
+
* (NO `ionViewWillEnter`) porque `val-page-wrapper` usa `<router-outlet>`
|
|
263
|
+
* plano — los hooks `ionView*` solo disparan dentro de `<ion-router-outlet>`.
|
|
264
|
+
*/
|
|
265
|
+
ngOnInit() {
|
|
266
|
+
this.pageRefresh.register(() => this.reload());
|
|
267
|
+
}
|
|
268
|
+
/** Quita el handler al destruir la vista — el refresher desaparece. */
|
|
269
|
+
ngOnDestroy() {
|
|
270
|
+
this.pageRefresh.unregister();
|
|
271
|
+
}
|
|
272
|
+
/**
|
|
273
|
+
* Refresh manual: re-suscribe el stream Firestore (listener nuevo) vía el
|
|
274
|
+
* helper. Resuelve tras un margen breve — el stream es real-time y re-emite
|
|
275
|
+
* en milisegundos; el delay sólo mantiene el spinner visible lo justo.
|
|
276
|
+
*/
|
|
277
|
+
async reload() {
|
|
278
|
+
this._stream.reload();
|
|
279
|
+
await new Promise(r => setTimeout(r, 700));
|
|
280
|
+
}
|
|
281
|
+
// ---------------------------------------------------------------------------
|
|
282
|
+
// Per-item helpers (puros — usables desde template).
|
|
283
|
+
// ---------------------------------------------------------------------------
|
|
284
|
+
openButtonProps() {
|
|
285
|
+
return {
|
|
286
|
+
text: this.tt('open'),
|
|
287
|
+
color: 'dark',
|
|
288
|
+
fill: 'clear',
|
|
289
|
+
size: 'small',
|
|
290
|
+
shape: 'round',
|
|
291
|
+
type: 'button',
|
|
292
|
+
icon: { name: 'open-outline', slot: 'end' },
|
|
293
|
+
};
|
|
294
|
+
}
|
|
295
|
+
isExpanded(id) {
|
|
296
|
+
return this._expanded().has(id);
|
|
297
|
+
}
|
|
298
|
+
toggleExpand(id) {
|
|
299
|
+
const next = new Set(this._expanded());
|
|
300
|
+
if (next.has(id))
|
|
301
|
+
next.delete(id);
|
|
302
|
+
else
|
|
303
|
+
next.add(id);
|
|
304
|
+
this._expanded.set(next);
|
|
305
|
+
}
|
|
306
|
+
isLong(body) {
|
|
307
|
+
if (!body)
|
|
308
|
+
return false;
|
|
309
|
+
return body.length > 110 || body.includes('\n');
|
|
310
|
+
}
|
|
311
|
+
/**
|
|
312
|
+
* Icon resolver con orden de fallback:
|
|
313
|
+
* 1. notif.payload.icon (forward-compat, sin breaking change en schema)
|
|
314
|
+
* 2. mapa por notif.type
|
|
315
|
+
* 3. default notifications-outline
|
|
316
|
+
*/
|
|
317
|
+
resolveIcon(n) {
|
|
318
|
+
const hint = n.payload?.['icon'];
|
|
319
|
+
if (hint?.value) {
|
|
320
|
+
if (hint.type === 'image' || hint.type === 'avatar') {
|
|
321
|
+
return { kind: hint.type, src: hint.value };
|
|
322
|
+
}
|
|
323
|
+
// Ignoramos hint.color — todos los iconos van en dark por convención UX.
|
|
324
|
+
return { kind: 'ionicon', name: hint.value, color: 'dark' };
|
|
325
|
+
}
|
|
326
|
+
const t = n.type;
|
|
327
|
+
const name = (() => {
|
|
328
|
+
switch (t) {
|
|
329
|
+
case 'approval':
|
|
330
|
+
return 'checkmark-circle-outline';
|
|
331
|
+
case 'chat':
|
|
332
|
+
case 'chatbot':
|
|
333
|
+
return 'chatbubble-outline';
|
|
334
|
+
case 'comment':
|
|
335
|
+
return 'chatbox-ellipses-outline';
|
|
336
|
+
case 'reminder':
|
|
337
|
+
return 'alarm-outline';
|
|
338
|
+
case 'system':
|
|
339
|
+
return 'cog-outline';
|
|
340
|
+
case 'user':
|
|
341
|
+
case 'mention':
|
|
342
|
+
return 'person-outline';
|
|
343
|
+
case 'document':
|
|
344
|
+
return 'document-text-outline';
|
|
345
|
+
default:
|
|
346
|
+
return 'notifications-outline';
|
|
347
|
+
}
|
|
348
|
+
})();
|
|
349
|
+
return { kind: 'ionicon', name, color: 'dark' };
|
|
350
|
+
}
|
|
351
|
+
ioniconName(n) {
|
|
352
|
+
const r = this.resolveIcon(n);
|
|
353
|
+
return r.kind === 'ionicon' ? r.name : '';
|
|
354
|
+
}
|
|
355
|
+
ioniconColor(n) {
|
|
356
|
+
const r = this.resolveIcon(n);
|
|
357
|
+
return r.kind === 'ionicon' ? r.color : undefined;
|
|
358
|
+
}
|
|
359
|
+
imageSrc(n) {
|
|
360
|
+
const r = this.resolveIcon(n);
|
|
361
|
+
return r.kind === 'image' || r.kind === 'avatar' ? r.src : '';
|
|
362
|
+
}
|
|
363
|
+
ionColor(token) {
|
|
364
|
+
if (!token)
|
|
365
|
+
return 'var(--ion-color-primary)';
|
|
366
|
+
return `var(--ion-color-${token})`;
|
|
367
|
+
}
|
|
368
|
+
relativeTime(n) {
|
|
369
|
+
const d = n.createdAt instanceof Date ? n.createdAt : null;
|
|
370
|
+
if (!d)
|
|
371
|
+
return '';
|
|
372
|
+
const diffMs = Date.now() - d.getTime();
|
|
373
|
+
const min = Math.floor(diffMs / 60000);
|
|
374
|
+
if (min < 1)
|
|
375
|
+
return this.tt('timeNow');
|
|
376
|
+
if (min < 60)
|
|
377
|
+
return this.tt('timeMinutes').replace('{n}', String(min));
|
|
378
|
+
const h = Math.floor(min / 60);
|
|
379
|
+
if (h < 24)
|
|
380
|
+
return this.tt('timeHours').replace('{n}', String(h));
|
|
381
|
+
const days = Math.floor(h / 24);
|
|
382
|
+
return this.tt('timeDays').replace('{n}', String(days));
|
|
383
|
+
}
|
|
384
|
+
/** Devuelve label "Desde {appName}" si la notif viene de otra app, sino null. */
|
|
385
|
+
showCrossAppBadge(n) {
|
|
386
|
+
const currentApp = 'showcase';
|
|
387
|
+
if (!n.appId || n.appId === currentApp)
|
|
388
|
+
return null;
|
|
389
|
+
return this.tt('crossApp').replace('{app}', n.appId);
|
|
390
|
+
}
|
|
391
|
+
// ---------------------------------------------------------------------------
|
|
392
|
+
// Actions
|
|
393
|
+
// ---------------------------------------------------------------------------
|
|
394
|
+
async onOpen(n) {
|
|
395
|
+
try {
|
|
396
|
+
const result = await this.action.open(n);
|
|
397
|
+
this.resolvedConfig().onNotificationOpen?.(n, result);
|
|
398
|
+
}
|
|
399
|
+
catch (err) {
|
|
400
|
+
this.errors.handle(err, {
|
|
401
|
+
context: 'notifications.open',
|
|
402
|
+
fallbackKey: 'openError',
|
|
403
|
+
i18nNamespace: this.ns,
|
|
404
|
+
});
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
async onMarkAll() {
|
|
408
|
+
if (this._bulkBusy())
|
|
409
|
+
return;
|
|
410
|
+
this._bulkBusy.set(true);
|
|
411
|
+
try {
|
|
412
|
+
await this.notifs.markAllAsRead();
|
|
413
|
+
this.toast.show({
|
|
414
|
+
message: this.tt('markedAllSuccess'),
|
|
415
|
+
color: 'dark',
|
|
416
|
+
duration: 2500,
|
|
417
|
+
position: 'top',
|
|
418
|
+
});
|
|
419
|
+
}
|
|
420
|
+
catch (err) {
|
|
421
|
+
this.errors.handle(err, {
|
|
422
|
+
context: 'notifications.markAll',
|
|
423
|
+
fallbackKey: 'markedAllError',
|
|
424
|
+
i18nNamespace: this.ns,
|
|
425
|
+
});
|
|
426
|
+
}
|
|
427
|
+
finally {
|
|
428
|
+
this._bulkBusy.set(false);
|
|
429
|
+
}
|
|
430
|
+
}
|
|
431
|
+
onLoadMore() {
|
|
432
|
+
if (this._loadingMore())
|
|
433
|
+
return;
|
|
434
|
+
this._loadingMore.set(true);
|
|
435
|
+
// Slice viene del cache local — no hay fetch real, pero un breve spinner
|
|
436
|
+
// confirma al user que el click registró y suaviza la aparición de items.
|
|
437
|
+
setTimeout(() => {
|
|
438
|
+
this._pageSize.update(n => n + this.pageStep);
|
|
439
|
+
this._loadingMore.set(false);
|
|
440
|
+
}, 250);
|
|
441
|
+
}
|
|
442
|
+
onGoToSettings() {
|
|
443
|
+
this.nav.navigateByUrl(this.resolvedConfig().settingsNotificationsPath);
|
|
444
|
+
}
|
|
445
|
+
// ---------------------------------------------------------------------------
|
|
446
|
+
// Grouping helpers
|
|
447
|
+
// ---------------------------------------------------------------------------
|
|
448
|
+
bucketOf(n, now) {
|
|
449
|
+
const d = n.createdAt instanceof Date ? n.createdAt : null;
|
|
450
|
+
if (!d)
|
|
451
|
+
return 'earlier';
|
|
452
|
+
if (d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth() && d.getDate() === now.getDate()) {
|
|
453
|
+
return 'today';
|
|
454
|
+
}
|
|
455
|
+
if (d.getFullYear() === now.getFullYear() && d.getMonth() === now.getMonth()) {
|
|
456
|
+
return 'thisMonth';
|
|
457
|
+
}
|
|
458
|
+
return 'earlier';
|
|
459
|
+
}
|
|
460
|
+
tt(key) {
|
|
461
|
+
return this.i18n.t(key, this.ns);
|
|
462
|
+
}
|
|
463
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NotificationsViewComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
464
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.2.14", type: NotificationsViewComponent, isStandalone: true, selector: "val-notifications-view", inputs: { config: "config" }, ngImport: i0, template: `
|
|
465
|
+
<div class="page">
|
|
466
|
+
<header class="page-header">
|
|
467
|
+
<val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
|
|
468
|
+
<val-title
|
|
469
|
+
[props]="{
|
|
470
|
+
size: 'large',
|
|
471
|
+
color: 'dark',
|
|
472
|
+
bold: false,
|
|
473
|
+
content: pageDescription(),
|
|
474
|
+
}"
|
|
475
|
+
/>
|
|
476
|
+
@if (showMarkAll()) {
|
|
477
|
+
<div class="row-actions">
|
|
478
|
+
<val-button [props]="markAllButtonProps()" (click)="onMarkAll()" />
|
|
479
|
+
</div>
|
|
480
|
+
}
|
|
481
|
+
</header>
|
|
482
|
+
|
|
483
|
+
@if (resolvedConfig().showPushOffCta && !pushEnabled()) {
|
|
484
|
+
<section class="notif-cta">
|
|
485
|
+
<ion-icon class="notif-cta__icon" name="notifications-off-outline" aria-hidden="true" />
|
|
486
|
+
<div class="notif-cta__body">
|
|
487
|
+
<val-text
|
|
488
|
+
[props]="{
|
|
489
|
+
content: ctaTitle(),
|
|
490
|
+
size: 'medium',
|
|
491
|
+
color: 'dark',
|
|
492
|
+
bold: true,
|
|
493
|
+
}"
|
|
494
|
+
/>
|
|
495
|
+
<val-text
|
|
496
|
+
[props]="{
|
|
497
|
+
content: ctaHint(),
|
|
498
|
+
size: 'small',
|
|
499
|
+
color: 'medium',
|
|
500
|
+
bold: false,
|
|
501
|
+
}"
|
|
502
|
+
/>
|
|
503
|
+
<div class="row-actions">
|
|
504
|
+
<val-button [props]="ctaButtonProps()" (click)="onGoToSettings()" />
|
|
505
|
+
</div>
|
|
506
|
+
</div>
|
|
507
|
+
</section>
|
|
508
|
+
}
|
|
509
|
+
|
|
510
|
+
@if (loading()) {
|
|
511
|
+
<val-skeleton-layout [props]="{ preset: 'list', rows: 6 }" />
|
|
512
|
+
} @else if (errorState()) {
|
|
513
|
+
<val-empty-state [props]="errorState()!" />
|
|
514
|
+
} @else if (allNotifs().length === 0) {
|
|
515
|
+
<val-empty-state [props]="emptyStateProps()" />
|
|
516
|
+
} @else {
|
|
517
|
+
@for (group of groups(); track group.key) {
|
|
518
|
+
<section class="group">
|
|
519
|
+
<val-title
|
|
520
|
+
[props]="{
|
|
521
|
+
size: 'medium',
|
|
522
|
+
color: 'dark',
|
|
523
|
+
bold: true,
|
|
524
|
+
content: group.label,
|
|
525
|
+
}"
|
|
526
|
+
/>
|
|
527
|
+
<ul class="notif-list">
|
|
528
|
+
@for (n of group.items; track n.id) {
|
|
529
|
+
<li class="notif" [class.notif--unread]="!n.isRead">
|
|
530
|
+
<div class="notif__icon">
|
|
531
|
+
@switch (resolveIcon(n).kind) {
|
|
532
|
+
@case ('ionicon') {
|
|
533
|
+
<ion-icon
|
|
534
|
+
[name]="ioniconName(n)"
|
|
535
|
+
[style.color]="ionColor(ioniconColor(n))"
|
|
536
|
+
aria-hidden="true"
|
|
537
|
+
/>
|
|
538
|
+
}
|
|
539
|
+
@case ('image') {
|
|
540
|
+
<img [src]="imageSrc(n)" alt="" loading="lazy" />
|
|
541
|
+
}
|
|
542
|
+
@case ('avatar') {
|
|
543
|
+
<img class="notif__avatar" [src]="imageSrc(n)" alt="" loading="lazy" />
|
|
544
|
+
}
|
|
545
|
+
}
|
|
546
|
+
</div>
|
|
547
|
+
|
|
548
|
+
<div class="notif__body">
|
|
549
|
+
<div class="notif__head">
|
|
550
|
+
<val-text
|
|
551
|
+
[props]="{
|
|
552
|
+
content: n.title || '—',
|
|
553
|
+
size: 'medium',
|
|
554
|
+
color: 'dark',
|
|
555
|
+
bold: true,
|
|
556
|
+
}"
|
|
557
|
+
/>
|
|
558
|
+
<span class="notif__time">{{ relativeTime(n) }}</span>
|
|
559
|
+
</div>
|
|
560
|
+
@if (n.body) {
|
|
561
|
+
<p class="notif__text" [class.notif__text--clamped]="!isExpanded(n.id) && isLong(n.body)">
|
|
562
|
+
{{ n.body }}
|
|
563
|
+
</p>
|
|
564
|
+
@if (isLong(n.body)) {
|
|
565
|
+
<button class="notif__expand" type="button" (click)="toggleExpand(n.id)">
|
|
566
|
+
{{ isExpanded(n.id) ? seeLess() : seeMore() }}
|
|
567
|
+
</button>
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
@if (showCrossAppBadge(n); as appName) {
|
|
571
|
+
<span class="notif__app">{{ appName }}</span>
|
|
572
|
+
}
|
|
573
|
+
@if (n.actionRoute) {
|
|
574
|
+
<div class="row-actions row-actions--end">
|
|
575
|
+
<val-button [props]="openButtonProps()" (click)="onOpen(n)" />
|
|
576
|
+
</div>
|
|
577
|
+
}
|
|
578
|
+
</div>
|
|
579
|
+
</li>
|
|
580
|
+
}
|
|
581
|
+
</ul>
|
|
582
|
+
</section>
|
|
583
|
+
}
|
|
584
|
+
|
|
585
|
+
@if (hasMore()) {
|
|
586
|
+
<div class="row-actions row-actions--center">
|
|
587
|
+
<val-button [props]="loadMoreButtonProps()" (click)="onLoadMore()" />
|
|
588
|
+
</div>
|
|
589
|
+
}
|
|
590
|
+
}
|
|
591
|
+
</div>
|
|
592
|
+
`, isInline: true, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.row-actions{margin-top:12px}.row-actions--center{display:flex;justify-content:center;margin-top:20px}.row-actions--end{display:flex;justify-content:flex-end;margin-top:8px}.notif-cta{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;margin-bottom:16px;border:1px solid var(--ion-color-light-shade, rgba(0, 0, 0, .08));border-radius:14px;background:var(--ion-color-light)}.notif-cta__icon{font-size:24px;color:var(--ion-color-dark, #1a1a1a);flex-shrink:0;margin-top:2px}.notif-cta__body{display:flex;flex-direction:column;gap:2px}.group{padding:12px 0}.group+.group{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.notif-list{list-style:none;padding:0;margin:12px 0 0;display:flex;flex-direction:column;gap:10px}.notif{display:grid;grid-template-columns:44px 1fr;gap:12px;padding:12px;border-radius:12px;background:transparent;transition:background .12s ease}.notif--unread{background:var(--ion-color-light, rgba(0, 0, 0, .04))}.notif__icon{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--ion-color-light, rgba(0, 0, 0, .06));overflow:hidden}.notif__icon ion-icon{font-size:22px}.notif__icon img{width:100%;height:100%;object-fit:cover}.notif__avatar{border-radius:50%}.notif__body{display:flex;flex-direction:column;gap:4px;min-width:0}.notif__head{display:flex;justify-content:space-between;align-items:baseline;gap:8px}.notif__time{font-size:12px;color:var(--ion-color-medium, #92949c);flex-shrink:0}.notif__text{margin:0;font-size:14px;line-height:1.4;color:var(--ion-color-dark, #1a1a1a);white-space:pre-wrap}.notif__text--clamped{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notif__expand{background:none;border:0;padding:0;font-size:13px;color:var(--ion-color-dark, #1a1a1a);cursor:pointer;align-self:flex-start;text-decoration:underline}.notif__app{font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--ion-color-medium, #92949c);margin-top:2px}\n"], dependencies: [{ kind: "component", type: IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }, { kind: "component", type: DisplayComponent, selector: "val-display", inputs: ["props"] }, { kind: "component", type: TitleComponent, selector: "val-title", inputs: ["props"] }, { kind: "component", type: TextComponent, selector: "val-text", inputs: ["props"] }, { kind: "component", type: ButtonComponent, selector: "val-button", inputs: ["preset", "props"], outputs: ["onClick"] }, { kind: "component", type: SkeletonLayoutComponent, selector: "val-skeleton-layout", inputs: ["props"] }, { kind: "component", type: EmptyStateComponent, selector: "val-empty-state", inputs: ["props"] }] }); }
|
|
593
|
+
}
|
|
594
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.2.14", ngImport: i0, type: NotificationsViewComponent, decorators: [{
|
|
595
|
+
type: Component,
|
|
596
|
+
args: [{ selector: 'val-notifications-view', standalone: true, imports: [
|
|
597
|
+
IonIcon,
|
|
598
|
+
DisplayComponent,
|
|
599
|
+
TitleComponent,
|
|
600
|
+
TextComponent,
|
|
601
|
+
ButtonComponent,
|
|
602
|
+
SkeletonLayoutComponent,
|
|
603
|
+
EmptyStateComponent,
|
|
604
|
+
], template: `
|
|
605
|
+
<div class="page">
|
|
606
|
+
<header class="page-header">
|
|
607
|
+
<val-display [props]="{ size: 'small', color: 'dark', content: pageTitle() }" />
|
|
608
|
+
<val-title
|
|
609
|
+
[props]="{
|
|
610
|
+
size: 'large',
|
|
611
|
+
color: 'dark',
|
|
612
|
+
bold: false,
|
|
613
|
+
content: pageDescription(),
|
|
614
|
+
}"
|
|
615
|
+
/>
|
|
616
|
+
@if (showMarkAll()) {
|
|
617
|
+
<div class="row-actions">
|
|
618
|
+
<val-button [props]="markAllButtonProps()" (click)="onMarkAll()" />
|
|
619
|
+
</div>
|
|
620
|
+
}
|
|
621
|
+
</header>
|
|
622
|
+
|
|
623
|
+
@if (resolvedConfig().showPushOffCta && !pushEnabled()) {
|
|
624
|
+
<section class="notif-cta">
|
|
625
|
+
<ion-icon class="notif-cta__icon" name="notifications-off-outline" aria-hidden="true" />
|
|
626
|
+
<div class="notif-cta__body">
|
|
627
|
+
<val-text
|
|
628
|
+
[props]="{
|
|
629
|
+
content: ctaTitle(),
|
|
630
|
+
size: 'medium',
|
|
631
|
+
color: 'dark',
|
|
632
|
+
bold: true,
|
|
633
|
+
}"
|
|
634
|
+
/>
|
|
635
|
+
<val-text
|
|
636
|
+
[props]="{
|
|
637
|
+
content: ctaHint(),
|
|
638
|
+
size: 'small',
|
|
639
|
+
color: 'medium',
|
|
640
|
+
bold: false,
|
|
641
|
+
}"
|
|
642
|
+
/>
|
|
643
|
+
<div class="row-actions">
|
|
644
|
+
<val-button [props]="ctaButtonProps()" (click)="onGoToSettings()" />
|
|
645
|
+
</div>
|
|
646
|
+
</div>
|
|
647
|
+
</section>
|
|
648
|
+
}
|
|
649
|
+
|
|
650
|
+
@if (loading()) {
|
|
651
|
+
<val-skeleton-layout [props]="{ preset: 'list', rows: 6 }" />
|
|
652
|
+
} @else if (errorState()) {
|
|
653
|
+
<val-empty-state [props]="errorState()!" />
|
|
654
|
+
} @else if (allNotifs().length === 0) {
|
|
655
|
+
<val-empty-state [props]="emptyStateProps()" />
|
|
656
|
+
} @else {
|
|
657
|
+
@for (group of groups(); track group.key) {
|
|
658
|
+
<section class="group">
|
|
659
|
+
<val-title
|
|
660
|
+
[props]="{
|
|
661
|
+
size: 'medium',
|
|
662
|
+
color: 'dark',
|
|
663
|
+
bold: true,
|
|
664
|
+
content: group.label,
|
|
665
|
+
}"
|
|
666
|
+
/>
|
|
667
|
+
<ul class="notif-list">
|
|
668
|
+
@for (n of group.items; track n.id) {
|
|
669
|
+
<li class="notif" [class.notif--unread]="!n.isRead">
|
|
670
|
+
<div class="notif__icon">
|
|
671
|
+
@switch (resolveIcon(n).kind) {
|
|
672
|
+
@case ('ionicon') {
|
|
673
|
+
<ion-icon
|
|
674
|
+
[name]="ioniconName(n)"
|
|
675
|
+
[style.color]="ionColor(ioniconColor(n))"
|
|
676
|
+
aria-hidden="true"
|
|
677
|
+
/>
|
|
678
|
+
}
|
|
679
|
+
@case ('image') {
|
|
680
|
+
<img [src]="imageSrc(n)" alt="" loading="lazy" />
|
|
681
|
+
}
|
|
682
|
+
@case ('avatar') {
|
|
683
|
+
<img class="notif__avatar" [src]="imageSrc(n)" alt="" loading="lazy" />
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
</div>
|
|
687
|
+
|
|
688
|
+
<div class="notif__body">
|
|
689
|
+
<div class="notif__head">
|
|
690
|
+
<val-text
|
|
691
|
+
[props]="{
|
|
692
|
+
content: n.title || '—',
|
|
693
|
+
size: 'medium',
|
|
694
|
+
color: 'dark',
|
|
695
|
+
bold: true,
|
|
696
|
+
}"
|
|
697
|
+
/>
|
|
698
|
+
<span class="notif__time">{{ relativeTime(n) }}</span>
|
|
699
|
+
</div>
|
|
700
|
+
@if (n.body) {
|
|
701
|
+
<p class="notif__text" [class.notif__text--clamped]="!isExpanded(n.id) && isLong(n.body)">
|
|
702
|
+
{{ n.body }}
|
|
703
|
+
</p>
|
|
704
|
+
@if (isLong(n.body)) {
|
|
705
|
+
<button class="notif__expand" type="button" (click)="toggleExpand(n.id)">
|
|
706
|
+
{{ isExpanded(n.id) ? seeLess() : seeMore() }}
|
|
707
|
+
</button>
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
@if (showCrossAppBadge(n); as appName) {
|
|
711
|
+
<span class="notif__app">{{ appName }}</span>
|
|
712
|
+
}
|
|
713
|
+
@if (n.actionRoute) {
|
|
714
|
+
<div class="row-actions row-actions--end">
|
|
715
|
+
<val-button [props]="openButtonProps()" (click)="onOpen(n)" />
|
|
716
|
+
</div>
|
|
717
|
+
}
|
|
718
|
+
</div>
|
|
719
|
+
</li>
|
|
720
|
+
}
|
|
721
|
+
</ul>
|
|
722
|
+
</section>
|
|
723
|
+
}
|
|
724
|
+
|
|
725
|
+
@if (hasMore()) {
|
|
726
|
+
<div class="row-actions row-actions--center">
|
|
727
|
+
<val-button [props]="loadMoreButtonProps()" (click)="onLoadMore()" />
|
|
728
|
+
</div>
|
|
729
|
+
}
|
|
730
|
+
}
|
|
731
|
+
</div>
|
|
732
|
+
`, styles: [".page{padding:16px 0;max-width:720px;margin:0 auto}.page-header{margin-bottom:16px}.row-actions{margin-top:12px}.row-actions--center{display:flex;justify-content:center;margin-top:20px}.row-actions--end{display:flex;justify-content:flex-end;margin-top:8px}.notif-cta{display:flex;gap:12px;align-items:flex-start;padding:14px 16px;margin-bottom:16px;border:1px solid var(--ion-color-light-shade, rgba(0, 0, 0, .08));border-radius:14px;background:var(--ion-color-light)}.notif-cta__icon{font-size:24px;color:var(--ion-color-dark, #1a1a1a);flex-shrink:0;margin-top:2px}.notif-cta__body{display:flex;flex-direction:column;gap:2px}.group{padding:12px 0}.group+.group{border-top:1px solid var(--val-border-color, rgba(0, 0, 0, .08))}.notif-list{list-style:none;padding:0;margin:12px 0 0;display:flex;flex-direction:column;gap:10px}.notif{display:grid;grid-template-columns:44px 1fr;gap:12px;padding:12px;border-radius:12px;background:transparent;transition:background .12s ease}.notif--unread{background:var(--ion-color-light, rgba(0, 0, 0, .04))}.notif__icon{width:44px;height:44px;border-radius:50%;display:flex;align-items:center;justify-content:center;background:var(--ion-color-light, rgba(0, 0, 0, .06));overflow:hidden}.notif__icon ion-icon{font-size:22px}.notif__icon img{width:100%;height:100%;object-fit:cover}.notif__avatar{border-radius:50%}.notif__body{display:flex;flex-direction:column;gap:4px;min-width:0}.notif__head{display:flex;justify-content:space-between;align-items:baseline;gap:8px}.notif__time{font-size:12px;color:var(--ion-color-medium, #92949c);flex-shrink:0}.notif__text{margin:0;font-size:14px;line-height:1.4;color:var(--ion-color-dark, #1a1a1a);white-space:pre-wrap}.notif__text--clamped{display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden}.notif__expand{background:none;border:0;padding:0;font-size:13px;color:var(--ion-color-dark, #1a1a1a);cursor:pointer;align-self:flex-start;text-decoration:underline}.notif__app{font-size:11px;text-transform:uppercase;letter-spacing:.4px;color:var(--ion-color-medium, #92949c);margin-top:2px}\n"] }]
|
|
733
|
+
}], ctorParameters: () => [], propDecorators: { config: [{
|
|
734
|
+
type: Input
|
|
735
|
+
}] } });
|
|
736
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoibm90aWZpY2F0aW9ucy12aWV3LmNvbXBvbmVudC5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uLy4uLy4uL3NyYy9saWIvY29tcG9uZW50cy9vcmdhbmlzbXMvbm90aWZpY2F0aW9ucy12aWV3L25vdGlmaWNhdGlvbnMtdmlldy5jb21wb25lbnQudHMiXSwibmFtZXMiOltdLCJtYXBwaW5ncyI6IkFBQUEsT0FBTyxFQUFFLFNBQVMsRUFBRSxRQUFRLEVBQUUsTUFBTSxFQUFFLE1BQU0sRUFBRSxLQUFLLEVBQXFCLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN0RyxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0saUJBQWlCLENBQUM7QUFDakQsT0FBTyxFQUFFLE9BQU8sRUFBRSxNQUFNLDJCQUEyQixDQUFDO0FBQ3BELE9BQU8sRUFBRSxRQUFRLEVBQUUsTUFBTSxVQUFVLENBQUM7QUFDcEMsT0FBTyxFQUNMLFlBQVksRUFDWixzQkFBc0IsRUFDdEIsaUJBQWlCLEVBQ2pCLHNCQUFzQixFQUN0QixvQkFBb0IsRUFDcEIsbUJBQW1CLEVBQ25CLFVBQVUsRUFDVixtQkFBbUIsRUFDbkIsdUJBQXVCLEVBQ3ZCLG9CQUFvQixFQUNwQixXQUFXLEVBQ1gsYUFBYSxHQUNkLE1BQU0sZ0JBQWdCLENBQUM7QUFFeEIsT0FBTyxFQUFFLGVBQWUsRUFBRSxNQUFNLHFDQUFxQyxDQUFDO0FBQ3RFLE9BQU8sRUFBRSxnQkFBZ0IsRUFBRSxNQUFNLHVDQUF1QyxDQUFDO0FBQ3pFLE9BQU8sRUFBRSxhQUFhLEVBQUUsTUFBTSxpQ0FBaUMsQ0FBQztBQUNoRSxPQUFPLEVBQUUsY0FBYyxFQUFFLE1BQU0sbUNBQW1DLENBQUM7QUFDbkUsT0FBTyxFQUFFLG1CQUFtQixFQUFFLE1BQU0sbURBQW1ELENBQUM7QUFFeEYsT0FBTyxFQUFFLHFCQUFxQixFQUFFLE1BQU0scUNBQXFDLENBQUM7QUFDNUUsT0FBTyxFQUFFLHVCQUF1QixFQUFFLE1BQU0s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LEVBQUUsSUFBSSxDQUFDLEVBQUUsQ0FBQyxDQUFDO0lBQ25DLENBQUM7K0dBcGJVLDBCQUEwQjttR0FBMUIsMEJBQTBCLGdIQXBSM0I7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7O0dBZ0lULHNuRUF4SUMsT0FBTywySkFDUCxnQkFBZ0IsMkVBQ2hCLGNBQWMseUVBQ2QsYUFBYSx3RUFDYixlQUFlLDBHQUNmLHVCQUF1QixtRkFDdkIsbUJBQW1COzs0RkFzUlYsMEJBQTBCO2tCQWhTdEMsU0FBUzsrQkFDRSx3QkFBd0IsY0FDdEIsSUFBSSxXQUNQO3dCQUNQLE9BQU87d0JBQ1AsZ0JBQWdCO3dCQUNoQixjQUFjO3dCQUNkLGFBQWE7d0JBQ2IsZUFBZTt3QkFDZix1QkFBdUI7d0JBQ3ZCLG1CQUFtQjtxQkFDcEIsWUFDUzs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FnSVQ7d0RBdUtRLE1BQU07c0JBQWQsS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgY29tcHV0ZWQsIGVmZmVjdCwgaW5qZWN0LCBJbnB1dCwgT25EZXN0cm95LCBPbkluaXQsIHNpZ25hbCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgQWN0aXZhdGVkUm91dGUgfSBmcm9tICdAYW5ndWxhci9yb3V0ZXInO1xuaW1wb3J0IHsgSW9uSWNvbiB9IGZyb20gJ0Bpb25pYy9hbmd1bGFyL3N0YW5kYWxvbmUnO1xuaW1wb3J0IHsgYWRkSWNvbnMgfSBmcm9tICdpb25pY29ucyc7XG5pbXBvcnQge1xuICBhbGFybU91dGxpbmUsXG4gIGNoYXRib3hFbGxpcHNlc091dGxpbmUsXG4gIGNoYXRidWJibGVPdXRsaW5lLFxuICBjaGVja21hcmtDaXJjbGVPdXRsaW5lLFxuICBjaGVja21hcmtEb25lT3V0bGluZSxcbiAgY2xvdWRPZmZsaW5lT3V0bGluZSxcbiAgY29nT3V0bGluZSxcbiAgZG9jdW1lbnRUZXh0T3V0bGluZSxcbiAgbm90aWZpY2F0aW9uc09mZk91dGxpbmUsXG4gIG5vdGlmaWNhdGlvbnNPdXRsaW5lLFxuICBvcGVuT3V0bGluZSxcbiAgcGVyc29uT3V0bGluZSxcbn0gZnJvbSAnaW9uaWNvbnMvaWNvbnMnO1xuXG5pbXBvcnQgeyBCdXR0b25Db21wb25lbnQgfSBmcm9tICcuLi8uLi9hdG9tcy9idXR0b24vYnV0dG9uLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBEaXNwbGF5Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vYXRvbXMvZGlzcGxheS9kaXNwbGF5LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUZXh0Q29tcG9uZW50IH0gZnJvbSAnLi4vLi4vYXRvbXMvdGV4dC90ZXh0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBUaXRsZUNvbXBvbmVudCB9IGZyb20gJy4uLy4uL2F0b21zL3RpdGxlL3RpdGxlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBFbXB0eVN0YXRlQ29tcG9uZW50IH0gZnJvbSAnLi4vLi4vbW9sZWN1bGVzL2VtcHR5LXN0YXRlL2VtcHR5LXN0YXRlLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBFbXB0eVN0YXRlTWV0YWRhdGEgfSBmcm9tICcuLi8uLi9tb2xlY3VsZXMvZW1wdHktc3RhdGUvdHlwZXMnO1xuaW1wb3J0IHsgY3JlYXRlRXJyb3JTdGF0ZVByb3BzIH0gZnJvbSAnLi4vLi4vbW9sZWN1bGVzL2VtcHR5LXN0YXRlL2ZhY3RvcnknO1xuaW1wb3J0IHsgU2tlbGV0b25MYXlvdXRDb21wb25lbnQgfSBmcm9tICcuLi9za2VsZXRvbi1sYXlvdXQvc2tlbGV0b24tbGF5b3V0LmNvbXBvbmVudCc7XG5pbXBvcnQgeyBCdXR0b25NZXRhZGF0YSwgQ29tcG9uZW50U3RhdGVzIH0gZnJvbSAnLi4vLi4vdHlwZXMnO1xuXG5pbXBvcnQgeyBBdXRoU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2F1dGgvYXV0aC5zZXJ2aWNlJztcbmltcG9ydCB7IE5vdGlmaWNhdGlvbkFjdGlvblNlcnZpY2UgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9hdXRoL25vdGlmaWNhdGlvbi1hY3Rpb24uc2VydmljZSc7XG5pbXBvcnQgeyBJMThuU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL2kxOG4nO1xuaW1wb3J0IHsgaW50ZXJwcmV0RXJyb3IgfSBmcm9tICcuLi8uLi8uLi9zZXJ2aWNlcy9lcnJvcnMvaW50ZXJwcmV0LWVycm9yJztcbmltcG9ydCB7IE5hdmlnYXRpb25TZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvbmF2aWdhdGlvbi9uYXZpZ2F0aW9uLnNlcnZpY2UnO1xuaW1wb3J0IHsgTm90aWZpY2F0aW9uRG9jdW1lbnQsIE5vdGlmaWNhdGlvbnNTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvZmlyZWJhc2Uvbm90aWZpY2F0aW9ucy5zZXJ2aWNlJztcbmltcG9ydCB7IFBhZ2VSZWZyZXNoU2VydmljZSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL3BhZ2UtcmVmcmVzaC9wYWdlLXJlZnJlc2guc2VydmljZSc7XG5pbXBvcnQgeyBjcmVhdGVSZWZyZXNoYWJsZVN0cmVhbSB9IGZyb20gJy4uLy4uLy4uL3NlcnZpY2VzL3JlZnJlc2hhYmxlLXN0cmVhbS9yZWZyZXNoYWJsZS1zdHJlYW0nO1xuaW1wb3J0IHsgVG9hc3RTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvdG9hc3Quc2VydmljZSc7XG5pbXBvcnQgeyBWYWx0ZWNoRXJyb3JTZXJ2aWNlIH0gZnJvbSAnLi4vLi4vLi4vc2VydmljZXMvZXJyb3JzL3ZhbHRlY2gtZXJyb3Iuc2VydmljZSc7XG5cbmltcG9ydCB7IE5vdGlmaWNhdGlvbnNWaWV3Q29uZmlnIH0gZnJvbSAnLi90eXBlcyc7XG5pbXBvcnQgeyBOT1RJRklDQVRJT05TX1ZJRVdfSTE4TiB9IGZyb20gJy4vbm90aWZpY2F0aW9ucy12aWV3LmkxOG4nO1xuXG5hZGRJY29ucyh7XG4gIGFsYXJtT3V0bGluZSxcbiAgY2hhdGJveEVsbGlwc2VzT3V0bGluZSxcbiAgY2hhdGJ1YmJsZU91dGxpbmUsXG4gIGNoZWNrbWFya0NpcmNsZU91dGxpbmUsXG4gIGNoZWNrbWFya0RvbmVPdXRsaW5lLFxuICBjbG91ZE9mZmxpbmVPdXRsaW5lLFxuICBjb2dPdXRsaW5lLFxuICBkb2N1bWVudFRleHRPdXRsaW5lLFxuICBub3RpZmljYXRpb25zT2ZmT3V0bGluZSxcbiAgbm90aWZpY2F0aW9uc091dGxpbmUsXG4gIG9wZW5PdXRsaW5lLFxuICBwZXJzb25PdXRsaW5lLFxufSk7XG5cbmNvbnN0IERFRkFVTFRfTkFNRVNQQUNFID0gJ05vdGlmaWNhdGlvbnMnO1xuY29uc3QgREVGQVVMVF9TRVRUSU5HU19QQVRIID0gJy9hcHAvc2V0dGluZ3Mvbm90aWZpY2F0aW9ucyc7XG5jb25zdCBERUZBVUxUX1BBR0VfU0laRSA9IDEwO1xuY29uc3QgREVGQVVMVF9NQVhfTE9BRCA9IDUwO1xuXG50eXBlIEdyb3VwS2V5ID0gJ3RvZGF5JyB8ICd0aGlzTW9udGgnIHwgJ2VhcmxpZXInO1xuXG5pbnRlcmZhY2UgTm90aWZpY2F0aW9uR3JvdXAge1xuICBrZXk6IEdyb3VwS2V5O1xuICBsYWJlbDogc3RyaW5nO1xuICBpdGVtczogTm90aWZpY2F0aW9uRG9jdW1lbnRbXTtcbn1cblxudHlwZSBSZXNvbHZlZEljb24gPVxuICB8IHsga2luZDogJ2lvbmljb24nOyBuYW1lOiBzdHJpbmc7IGNvbG9yPzogc3RyaW5nIH1cbiAgfCB7IGtpbmQ6ICdpbWFnZSc7IHNyYzogc3RyaW5nIH1cbiAgfCB7IGtpbmQ6ICdhdmF0YXInOyBzcmM6IHN0cmluZyB9O1xuXG5pbnRlcmZhY2UgSWNvbkhpbnQge1xuICB0eXBlPzogJ2lvbmljb24nIHwgJ2ltYWdlJyB8ICdhdmF0YXInO1xuICB2YWx1ZT86IHN0cmluZztcbiAgY29sb3I/OiBzdHJpbmc7XG59XG5cbi8qKlxuICogYHZhbC1ub3RpZmljYXRpb25zLXZpZXdgIOKAlCBpbmJveCBkZSBub3RpZmljYWNpb25lcyBmdWxsLWZlYXR1cmUgYXV0b2NvbnRlbmlkb1xuICogKG9yZ2FuaXNtKS4gUHJvbW92aWRvIGRlc2RlIGBzaG93Y2FzZWAgYmFqbyBlbCBwcm9jZXNvIGRlIEFEUi0wMjEuXG4gKlxuICogU2VwYXJhZG8gZGUgYC9hcHAvc2V0dGluZ3Mvbm90aWZpY2F0aW9uc2AgKHF1ZSBjb250cm9sYSBwZXJtaXNvIEZDTSArIG1hc3RlclxuICogdG9nZ2xlKS4gQXF1w60gZWwgdXNlciBsZWUvYWJyZS9tYXJjYS1sZcOtZGFzIHN1cyBtZW5zYWplcy5cbiAqXG4gKiAtICoqU3RyZWFtIHJlYWwtdGltZSoqIHbDrWEgYE5vdGlmaWNhdGlvbnNTZXJ2aWNlLmdldEFsbChtYXhMb2FkKWAgZW52dWVsdG8gZW5cbiAqICAgYGNyZWF0ZVJlZnJlc2hhYmxlU3RyZWFtYCAoZ2F0ZWFkbyBwb3IgYGZpcmViYXNlQXV0aFJlYWR5YCwgcmV0cnkgY29ydG8sXG4gKiAgIGBmaXJzdEVtaXRUaW1lb3V0TXM6IDE1MDAwYCkuIEVzdGFkb3M6IGxvYWRpbmcgKHNrZWxldG9uKSwgZXJyb3JcbiAqICAgKGB2YWwtZW1wdHktc3RhdGVgICsgcmVpbnRlbnRhciksIGVtcHR5IChgdmFsLWVtcHR5LXN0YXRlYCArIENUQSksIGRhdGFcbiAqICAgKGxpc3RhIGFncnVwYWRhIEhveSAvIEVzdGUgbWVzIC8gQW50ZXJpb3JlcykuXG4gKiAtICoqQWJyaXIqKiB1bmEgbm90aWYg4oaSIGBOb3RpZmljYXRpb25BY3Rpb25TZXJ2aWNlLm9wZW4oKWAgKG1hcmtSZWFkICtcbiAqICAgc3dpdGNoLW9yZyArIG5hdmVnYXIvaGFuZG9mZiBjcm9zcy1hcHApLiBIb29rIGBvbk5vdGlmaWNhdGlvbk9wZW5gIG9wY2lvbmFsLlxuICogLSAqKk1hcmNhciB0b2RhcyBjb21vIGxlw61kYXMqKiAoZ2F0ZWFkbyBwb3IgYGVuYWJsZU1hcmtBbGxgKS5cbiAqIC0gKipDVEEgcHVzaC1vZmYqKiBjdWFuZG8gZWwgcGVybWlzbyBkZWwgbmF2ZWdhZG9yIG5vIGVzdMOhIGNvbmNlZGlkbyAoZ2F0ZWFkb1xuICogICBwb3IgYHNob3dQdXNoT2ZmQ3RhYCk7IG5hdmVnYSBhIGBzZXR0aW5nc05vdGlmaWNhdGlvbnNQYXRoYC5cbiAqIC0gKipQYWdpbmFjacOzbiBzb2Z0Kiog4oCUIHNsaWNlIGxvY2FsIChgcGFnZVNpemVgLCArYHBhZ2VTaXplYCBwb3IgY2xpY2spIHNvYnJlIGVsXG4gKiAgIGNhY2hlIGRlbCBzdHJlYW07IGVsIHRvcGUgZGUgZmV0Y2ggZXMgYG1heExvYWRgLlxuICogLSAqKmkxOG4gYXV0by1yZWdpc3RyYWRvKiogZXMvZW4gYmFqbyBgaTE4bk5hbWVzcGFjZWAgKGRlZmF1bHQgYE5vdGlmaWNhdGlvbnNgKS5cbiAqXG4gKiBOTyByZW5kZXJpemEgaW9uLWNvbnRlbnQg4oCUIHZpdmUgZGVudHJvIGRlIHZhbC1wYWdlLXdyYXBwZXIuIGBSb3V0ZXJgIHlcbiAqIGBBY3RpdmF0ZWRSb3V0ZWAgc2UgaW55ZWN0YW4gYHsgb3B0aW9uYWw6IHRydWUgfWAg4oaSIGZ1bmNpb25hIHNpbiByb3V0ZXJcbiAqIChlbWJlYmlkYSAvIFN0b3J5Ym9vaykuIEVsIGZvcndhcmQtY29tcGF0IGljb24gcmVzb2x2ZXIgbGVlIGBub3RpZi5wYXlsb2FkLmljb25gXG4gKiBzaSBleGlzdGUgKGB7IHR5cGUsIHZhbHVlLCBjb2xvcj8gfWApLCBjYWUgYSB1biBtYXBhIHBvciBgbm90aWYudHlwZWAsIGx1ZWdvIGFcbiAqIGBub3RpZmljYXRpb25zLW91dGxpbmVgLlxuICovXG5AQ29tcG9uZW50KHtcbiAgc2VsZWN0b3I6ICd2YWwtbm90aWZpY2F0aW9ucy12aWV3JyxcbiAgc3RhbmRhbG9uZTogdHJ1ZSxcbiAgaW1wb3J0czogW1xuICAgIElvbkljb24sXG4gICAgRGlzcGxheUNvbXBvbmVudCxcbiAgICBUaXRsZUNvbXBvbmVudCxcbiAgICBUZXh0Q29tcG9uZW50LFxuICAgIEJ1dHRvbkNvbXBvbmVudCxcbiAgICBTa2VsZXRvbkxheW91dENvbXBvbmVudCxcbiAgICBFbXB0eVN0YXRlQ29tcG9uZW50LFxuICBdLFxuICB0ZW1wbGF0ZTogYFxuICAgIDxkaXYgY2xhc3M9XCJwYWdlXCI+XG4gICAgICA8aGVhZGVyIGNsYXNzPVwicGFnZS1oZWFkZXJcIj5cbiAgICAgICAgPHZhbC1kaXNwbGF5IFtwcm9wc109XCJ7IHNpemU6ICdzbWFsbCcsIGNvbG9yOiAnZGFyaycsIGNvbnRlbnQ6IHBhZ2VUaXRsZSgpIH1cIiAvPlxuICAgICAgICA8dmFsLXRpdGxlXG4gICAgICAgICAgW3Byb3BzXT1cIntcbiAgICAgICAgICAgIHNpemU6ICdsYXJnZScsXG4gICAgICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICAgICAgYm9sZDogZmFsc2UsXG4gICAgICAgICAgICBjb250ZW50OiBwYWdlRGVzY3JpcHRpb24oKSxcbiAgICAgICAgICB9XCJcbiAgICAgICAgLz5cbiAgICAgICAgQGlmIChzaG93TWFya0FsbCgpKSB7XG4gICAgICAgICAgPGRpdiBjbGFzcz1cInJvdy1hY3Rpb25zXCI+XG4gICAgICAgICAgICA8dmFsLWJ1dHRvbiBbcHJvcHNdPVwibWFya0FsbEJ1dHRvblByb3BzKClcIiAoY2xpY2spPVwib25NYXJrQWxsKClcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICA8L2hlYWRlcj5cblxuICAgICAgQGlmIChyZXNvbHZlZENvbmZpZygpLnNob3dQdXNoT2ZmQ3RhICYmICFwdXNoRW5hYmxlZCgpKSB7XG4gICAgICAgIDxzZWN0aW9uIGNsYXNzPVwibm90aWYtY3RhXCI+XG4gICAgICAgICAgPGlvbi1pY29uIGNsYXNzPVwibm90aWYtY3RhX19pY29uXCIgbmFtZT1cIm5vdGlmaWNhdGlvbnMtb2ZmLW91dGxpbmVcIiBhcmlhLWhpZGRlbj1cInRydWVcIiAvPlxuICAgICAgICAgIDxkaXYgY2xhc3M9XCJub3RpZi1jdGFfX2JvZHlcIj5cbiAgICAgICAgICAgIDx2YWwtdGV4dFxuICAgICAgICAgICAgICBbcHJvcHNdPVwie1xuICAgICAgICAgICAgICAgIGNvbnRlbnQ6IGN0YVRpdGxlKCksXG4gICAgICAgICAgICAgICAgc2l6ZTogJ21lZGl1bScsXG4gICAgICAgICAgICAgICAgY29sb3I6ICdkYXJrJyxcbiAgICAgICAgICAgICAgICBib2xkOiB0cnVlLFxuICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgIC8+XG4gICAgICAgICAgICA8dmFsLXRleHRcbiAgICAgICAgICAgICAgW3Byb3BzXT1cIntcbiAgICAgICAgICAgICAgICBjb250ZW50OiBjdGFIaW50KCksXG4gICAgICAgICAgICAgICAgc2l6ZTogJ3NtYWxsJyxcbiAgICAgICAgICAgICAgICBjb2xvcjogJ21lZGl1bScsXG4gICAgICAgICAgICAgICAgYm9sZDogZmFsc2UsXG4gICAgICAgICAgICAgIH1cIlxuICAgICAgICAgICAgLz5cbiAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJyb3ctYWN0aW9uc1wiPlxuICAgICAgICAgICAgICA8dmFsLWJ1dHRvbiBbcHJvcHNdPVwiY3RhQnV0dG9uUHJvcHMoKVwiIChjbGljayk9XCJvbkdvVG9TZXR0aW5ncygpXCIgLz5cbiAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICA8L3NlY3Rpb24+XG4gICAgICB9XG5cbiAgICAgIEBpZiAobG9hZGluZygpKSB7XG4gICAgICAgIDx2YWwtc2tlbGV0b24tbGF5b3V0IFtwcm9wc109XCJ7IHByZXNldDogJ2xpc3QnLCByb3dzOiA2IH1cIiAvPlxuICAgICAgfSBAZWxzZSBpZiAoZXJyb3JTdGF0ZSgpKSB7XG4gICAgICAgIDx2YWwtZW1wdHktc3RhdGUgW3Byb3BzXT1cImVycm9yU3RhdGUoKSFcIiAvPlxuICAgICAgfSBAZWxzZSBpZiAoYWxsTm90aWZzKCkubGVuZ3RoID09PSAwKSB7XG4gICAgICAgIDx2YWwtZW1wdHktc3RhdGUgW3Byb3BzXT1cImVtcHR5U3RhdGVQcm9wcygpXCIgLz5cbiAgICAgIH0gQGVsc2Uge1xuICAgICAgICBAZm9yIChncm91cCBvZiBncm91cHMoKTsgdHJhY2sgZ3JvdXAua2V5KSB7XG4gICAgICAgICAgPHNlY3Rpb24gY2xhc3M9XCJncm91cFwiPlxuICAgICAgICAgICAgPHZhbC10aXRsZVxuICAgICAgICAgICAgICBbcHJvcHNdPVwie1xuICAgICAgICAgICAgICAgIHNpemU6ICdtZWRpdW0nLFxuICAgICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgICAgYm9sZDogdHJ1ZSxcbiAgICAgICAgICAgICAgICBjb250ZW50OiBncm91cC5sYWJlbCxcbiAgICAgICAgICAgICAgfVwiXG4gICAgICAgICAgICAvPlxuICAgICAgICAgICAgPHVsIGNsYXNzPVwibm90aWYtbGlzdFwiPlxuICAgICAgICAgICAgICBAZm9yIChuIG9mIGdyb3VwLml0ZW1zOyB0cmFjayBuLmlkKSB7XG4gICAgICAgICAgICAgICAgPGxpIGNsYXNzPVwibm90aWZcIiBbY2xhc3Mubm90aWYtLXVucmVhZF09XCIhbi5pc1JlYWRcIj5cbiAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJub3RpZl9faWNvblwiPlxuICAgICAgICAgICAgICAgICAgICBAc3dpdGNoIChyZXNvbHZlSWNvbihuKS5raW5kKSB7XG4gICAgICAgICAgICAgICAgICAgICAgQGNhc2UgKCdpb25pY29uJykge1xuICAgICAgICAgICAgICAgICAgICAgICAgPGlvbi1pY29uXG4gICAgICAgICAgICAgICAgICAgICAgICAgIFtuYW1lXT1cImlvbmljb25OYW1lKG4pXCJcbiAgICAgICAgICAgICAgICAgICAgICAgICAgW3N0eWxlLmNvbG9yXT1cImlvbkNvbG9yKGlvbmljb25Db2xvcihuKSlcIlxuICAgICAgICAgICAgICAgICAgICAgICAgICBhcmlhLWhpZGRlbj1cInRydWVcIlxuICAgICAgICAgICAgICAgICAgICAgICAgLz5cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgQGNhc2UgKCdpbWFnZScpIHtcbiAgICAgICAgICAgICAgICAgICAgICAgIDxpbWcgW3NyY109XCJpbWFnZVNyYyhuKVwiIGFsdD1cIlwiIGxvYWRpbmc9XCJsYXp5XCIgLz5cbiAgICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICAgICAgQGNhc2UgKCdhdmF0YXInKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8aW1nIGNsYXNzPVwibm90aWZfX2F2YXRhclwiIFtzcmNdPVwiaW1hZ2VTcmMobilcIiBhbHQ9XCJcIiBsb2FkaW5nPVwibGF6eVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICB9XG4gICAgICAgICAgICAgICAgICA8L2Rpdj5cblxuICAgICAgICAgICAgICAgICAgPGRpdiBjbGFzcz1cIm5vdGlmX19ib2R5XCI+XG4gICAgICAgICAgICAgICAgICAgIDxkaXYgY2xhc3M9XCJub3RpZl9faGVhZFwiPlxuICAgICAgICAgICAgICAgICAgICAgIDx2YWwtdGV4dFxuICAgICAgICAgICAgICAgICAgICAgICAgW3Byb3BzXT1cIntcbiAgICAgICAgICAgICAgICAgICAgICAgICAgY29udGVudDogbi50aXRsZSB8fCAn4oCUJyxcbiAgICAgICAgICAgICAgICAgICAgICAgICAgc2l6ZTogJ21lZGl1bScsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGNvbG9yOiAnZGFyaycsXG4gICAgICAgICAgICAgICAgICAgICAgICAgIGJvbGQ6IHRydWUsXG4gICAgICAgICAgICAgICAgICAgICAgICB9XCJcbiAgICAgICAgICAgICAgICAgICAgICAvPlxuICAgICAgICAgICAgICAgICAgICAgIDxzcGFuIGNsYXNzPVwibm90aWZfX3RpbWVcIj57eyByZWxhdGl2ZVRpbWUobikgfX08L3NwYW4+XG4gICAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgICAgICBAaWYgKG4uYm9keSkge1xuICAgICAgICAgICAgICAgICAgICAgIDxwIGNsYXNzPVwibm90aWZfX3RleHRcIiBbY2xhc3Mubm90aWZfX3RleHQtLWNsYW1wZWRdPVwiIWlzRXhwYW5kZWQobi5pZCkgJiYgaXNMb25nKG4uYm9keSlcIj5cbiAgICAgICAgICAgICAgICAgICAgICAgIHt7IG4uYm9keSB9fVxuICAgICAgICAgICAgICAgICAgICAgIDwvcD5cbiAgICAgICAgICAgICAgICAgICAgICBAaWYgKGlzTG9uZyhuLmJvZHkpKSB7XG4gICAgICAgICAgICAgICAgICAgICAgICA8YnV0dG9uIGNsYXNzPVwibm90aWZfX2V4cGFuZFwiIHR5cGU9XCJidXR0b25cIiAoY2xpY2spPVwidG9nZ2xlRXhwYW5kKG4uaWQpXCI+XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHt7IGlzRXhwYW5kZWQobi5pZCkgPyBzZWVMZXNzKCkgOiBzZWVNb3JlKCkgfX1cbiAgICAgICAgICAgICAgICAgICAgICAgIDwvYnV0dG9uPlxuICAgICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBAaWYgKHNob3dDcm9zc0FwcEJhZGdlKG4pOyBhcyBhcHBOYW1lKSB7XG4gICAgICAgICAgICAgICAgICAgICAgPHNwYW4gY2xhc3M9XCJub3RpZl9fYXBwXCI+e3sgYXBwTmFtZSB9fTwvc3Bhbj5cbiAgICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgICBAaWYgKG4uYWN0aW9uUm91dGUpIHtcbiAgICAgICAgICAgICAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93LWFjdGlvbnMgcm93LWFjdGlvbnMtLWVuZFwiPlxuICAgICAgICAgICAgICAgICAgICAgICAgPHZhbC1idXR0b24gW3Byb3BzXT1cIm9wZW5CdXR0b25Qcm9wcygpXCIgKGNsaWNrKT1cIm9uT3BlbihuKVwiIC8+XG4gICAgICAgICAgICAgICAgICAgICAgPC9kaXY+XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIDwvZGl2PlxuICAgICAgICAgICAgICAgIDwvbGk+XG4gICAgICAgICAgICAgIH1cbiAgICAgICAgICAgIDwvdWw+XG4gICAgICAgICAgPC9zZWN0aW9uPlxuICAgICAgICB9XG5cbiAgICAgICAgQGlmIChoYXNNb3JlKCkpIHtcbiAgICAgICAgICA8ZGl2IGNsYXNzPVwicm93LWFjdGlvbnMgcm93LWFjdGlvbnMtLWNlbnRlclwiPlxuICAgICAgICAgICAgPHZhbC1idXR0b24gW3Byb3BzXT1cImxvYWRNb3JlQnV0dG9uUHJvcHMoKVwiIChjbGljayk9XCJvbkxvYWRNb3JlKClcIiAvPlxuICAgICAgICAgIDwvZGl2PlxuICAgICAgICB9XG4gICAgICB9XG4gICAgPC9kaXY+XG4gIGAsXG4gIHN0eWxlczogW1xuICAgIGBcbiAgICAgIC5wYWdlIHtcbiAgICAgICAgcGFkZGluZzogMTZweCAwO1xuICAgICAgICBtYXgtd2lkdGg6IDcyMHB4O1xuICAgICAgICBtYXJnaW46IDAgYXV0bztcbiAgICAgIH1cbiAgICAgIC5wYWdlLWhlYWRlciB7XG4gICAgICAgIG1hcmdpbi1ib3R0b206IDE2cHg7XG4gICAgICB9XG4gICAgICAucm93LWFjdGlvbnMge1xuICAgICAgICBtYXJnaW4tdG9wOiAxMnB4O1xuICAgICAgfVxuICAgICAgLnJvdy1hY3Rpb25zLS1jZW50ZXIge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBqdXN0aWZ5LWNvbnRlbnQ6IGNlbnRlcjtcbiAgICAgICAgbWFyZ2luLXRvcDogMjBweDtcbiAgICAgIH1cbiAgICAgIC5yb3ctYWN0aW9ucy0tZW5kIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBmbGV4LWVuZDtcbiAgICAgICAgbWFyZ2luLXRvcDogOHB4O1xuICAgICAgfVxuXG4gICAgICAubm90aWYtY3RhIHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZ2FwOiAxMnB4O1xuICAgICAgICBhbGlnbi1pdGVtczogZmxleC1zdGFydDtcbiAgICAgICAgcGFkZGluZzogMTRweCAxNnB4O1xuICAgICAgICBtYXJnaW4tYm90dG9tOiAxNnB4O1xuICAgICAgICAvKiBTdGVwLSogbm8gaW52aWVydGUgZW4gZGFyaywgdGV4dG8gbGlnaHQgKyBiZyBsaWdodCA9IGludmlzaWJsZS5cbiAgICAgICAgICAgbGlnaHQvbGlnaHQtc2hhZGUgc2kgZmxpcHBhbiBjb24gZWwgcGFsZXR0ZSBkYXJrIGRlIElvbmljLiAqL1xuICAgICAgICBib3JkZXI6IDFweCBzb2xpZCB2YXIoLS1pb24tY29sb3ItbGlnaHQtc2hhZGUsIHJnYmEoMCwgMCwgMCwgMC4wOCkpO1xuICAgICAgICBib3JkZXItcmFkaXVzOiAxNHB4O1xuICAgICAgICBiYWNrZ3JvdW5kOiB2YXIoLS1pb24tY29sb3ItbGlnaHQpO1xuICAgICAgfVxuICAgICAgLm5vdGlmLWN0YV9faWNvbiB7XG4gICAgICAgIGZvbnQtc2l6ZTogMjRweDtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi1jb2xvci1kYXJrLCAjMWExYTFhKTtcbiAgICAgICAgZmxleC1zaHJpbms6IDA7XG4gICAgICAgIG1hcmdpbi10b3A6IDJweDtcbiAgICAgIH1cbiAgICAgIC5ub3RpZi1jdGFfX2JvZHkge1xuICAgICAgICBkaXNwbGF5OiBmbGV4O1xuICAgICAgICBmbGV4LWRpcmVjdGlvbjogY29sdW1uO1xuICAgICAgICBnYXA6IDJweDtcbiAgICAgIH1cblxuICAgICAgLmdyb3VwIHtcbiAgICAgICAgcGFkZGluZzogMTJweCAwO1xuICAgICAgfVxuICAgICAgLmdyb3VwICsgLmdyb3VwIHtcbiAgICAgICAgYm9yZGVyLXRvcDogMXB4IHNvbGlkIHZhcigtLXZhbC1ib3JkZXItY29sb3IsIHJnYmEoMCwgMCwgMCwgMC4wOCkpO1xuICAgICAgfVxuXG4gICAgICAubm90aWYtbGlzdCB7XG4gICAgICAgIGxpc3Qtc3R5bGU6IG5vbmU7XG4gICAgICAgIHBhZGRpbmc6IDA7XG4gICAgICAgIG1hcmdpbjogMTJweCAwIDA7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGZsZXgtZGlyZWN0aW9uOiBjb2x1bW47XG4gICAgICAgIGdhcDogMTBweDtcbiAgICAgIH1cbiAgICAgIC5ub3RpZiB7XG4gICAgICAgIGRpc3BsYXk6IGdyaWQ7XG4gICAgICAgIGdyaWQtdGVtcGxhdGUtY29sdW1uczogNDRweCAxZnI7XG4gICAgICAgIGdhcDogMTJweDtcbiAgICAgICAgcGFkZGluZzogMTJweDtcbiAgICAgICAgYm9yZGVyLXJhZGl1czogMTJweDtcbiAgICAgICAgYmFja2dyb3VuZDogdHJhbnNwYXJlbnQ7XG4gICAgICAgIHRyYW5zaXRpb246IGJhY2tncm91bmQgMTIwbXMgZWFzZTtcbiAgICAgIH1cbiAgICAgIC5ub3RpZi0tdW5yZWFkIHtcbiAgICAgICAgYmFja2dyb3VuZDogdmFyKC0taW9uLWNvbG9yLWxpZ2h0LCByZ2JhKDAsIDAsIDAsIDAuMDQpKTtcbiAgICAgIH1cbiAgICAgIC5ub3RpZl9faWNvbiB7XG4gICAgICAgIHdpZHRoOiA0NHB4O1xuICAgICAgICBoZWlnaHQ6IDQ0cHg7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgYWxpZ24taXRlbXM6IGNlbnRlcjtcbiAgICAgICAganVzdGlmeS1jb250ZW50OiBjZW50ZXI7XG4gICAgICAgIGJhY2tncm91bmQ6IHZhcigtLWlvbi1jb2xvci1saWdodCwgcmdiYSgwLCAwLCAwLCAwLjA2KSk7XG4gICAgICAgIG92ZXJmbG93OiBoaWRkZW47XG4gICAgICB9XG4gICAgICAubm90aWZfX2ljb24gaW9uLWljb24ge1xuICAgICAgICBmb250LXNpemU6IDIycHg7XG4gICAgICB9XG4gICAgICAubm90aWZfX2ljb24gaW1nIHtcbiAgICAgICAgd2lkdGg6IDEwMCU7XG4gICAgICAgIGhlaWdodDogMTAwJTtcbiAgICAgICAgb2JqZWN0LWZpdDogY292ZXI7XG4gICAgICB9XG4gICAgICAubm90aWZfX2F2YXRhciB7XG4gICAgICAgIGJvcmRlci1yYWRpdXM6IDUwJTtcbiAgICAgIH1cblxuICAgICAgLm5vdGlmX19ib2R5IHtcbiAgICAgICAgZGlzcGxheTogZmxleDtcbiAgICAgICAgZmxleC1kaXJlY3Rpb246IGNvbHVtbjtcbiAgICAgICAgZ2FwOiA0cHg7XG4gICAgICAgIG1pbi13aWR0aDogMDtcbiAgICAgIH1cbiAgICAgIC5ub3RpZl9faGVhZCB7XG4gICAgICAgIGRpc3BsYXk6IGZsZXg7XG4gICAgICAgIGp1c3RpZnktY29udGVudDogc3BhY2UtYmV0d2VlbjtcbiAgICAgICAgYWxpZ24taXRlbXM6IGJhc2VsaW5lO1xuICAgICAgICBnYXA6IDhweDtcbiAgICAgIH1cbiAgICAgIC5ub3RpZl9fdGltZSB7XG4gICAgICAgIGZvbnQtc2l6ZTogMTJweDtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi1jb2xvci1tZWRpdW0sICM5Mjk0OWMpO1xuICAgICAgICBmbGV4LXNocmluazogMDtcbiAgICAgIH1cbiAgICAgIC5ub3RpZl9fdGV4dCB7XG4gICAgICAgIG1hcmdpbjogMDtcbiAgICAgICAgZm9udC1zaXplOiAxNHB4O1xuICAgICAgICBsaW5lLWhlaWdodDogMS40O1xuICAgICAgICBjb2xvcjogdmFyKC0taW9uLWNvbG9yLWRhcmssICMxYTFhMWEpO1xuICAgICAgICB3aGl0ZS1zcGFjZTogcHJlLXdyYXA7XG4gICAgICB9XG4gICAgICAubm90aWZfX3RleHQtLWNsYW1wZWQge1xuICAgICAgICBkaXNwbGF5OiAtd2Via2l0LWJveDtcbiAgICAgICAgLXdlYmtpdC1saW5lLWNsYW1wOiAyO1xuICAgICAgICAtd2Via2l0LWJveC1vcmllbnQ6IHZlcnRpY2FsO1xuICAgICAgICBvdmVyZmxvdzogaGlkZGVuO1xuICAgICAgfVxuICAgICAgLm5vdGlmX19leHBhbmQge1xuICAgICAgICBiYWNrZ3JvdW5kOiBub25lO1xuICAgICAgICBib3JkZXI6IDA7XG4gICAgICAgIHBhZGRpbmc6IDA7XG4gICAgICAgIGZvbnQtc2l6ZTogMTNweDtcbiAgICAgICAgY29sb3I6IHZhcigtLWlvbi1jb2xvci1kYXJrLCAjMWExYTFhKTtcbiAgICAgICAgY3Vyc29yOiBwb2ludGVyO1xuICAgICAgICBhbGlnbi1zZWxmOiBmbGV4LXN0YXJ0O1xuICAgICAgICB0ZXh0LWRlY29yYXRpb246IHVuZGVybGluZTtcbiAgICAgIH1cbiAgICAgIC5ub3RpZl9fYXBwIHtcbiAgICAgICAgZm9udC1zaXplOiAxMXB4O1xuICAgICAgICB0ZXh0LXRyYW5zZm9ybTogdXBwZXJjYXNlO1xuICAgICAgICBsZXR0ZXItc3BhY2luZzogMC40cHg7XG4gICAgICAgIGNvbG9yOiB2YXIoLS1pb24tY29sb3ItbWVkaXVtLCAjOTI5NDljKTtcbiAgICAgICAgbWFyZ2luLXRvcDogMnB4O1xuICAgICAgfVxuICAgIGAsXG4gIF0sXG59KVxuZXhwb3J0IGNsYXNzIE5vdGlmaWNhdGlvbnNWaWV3Q29tcG9uZW50IGltcGxlbWVudHMgT25Jbml0LCBPbkRlc3Ryb3kge1xuICBwcml2YXRlIG5hdiA9IGluamVjdChOYXZpZ2F0aW9uU2VydmljZSk7XG4gIHByaXZhdGUgaTE4biA9IGluamVjdChJMThuU2VydmljZSk7XG4gIHByaXZhdGUgbm90aWZzID0gaW5qZWN0KE5vdGlmaWNhdGlvbnNTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBhY3Rpb24gPSBpbmplY3QoTm90aWZpY2F0aW9uQWN0aW9uU2VydmljZSk7XG4gIHByaXZhdGUgdG9hc3QgPSBpbmplY3QoVG9hc3RTZXJ2aWNlKTtcbiAgcHJpdmF0ZSBlcnJvcnMgPSBpbmplY3QoVmFsdGVjaEVycm9yU2VydmljZSk7XG4gIHByaXZhdGUgYXV0aCA9IGluamVjdChBdXRoU2VydmljZSk7XG4gIHByaXZhdGUgcGFnZVJlZnJlc2ggPSBpbmplY3QoUGFnZVJlZnJlc2hTZXJ2aWNlKTtcbiAgLy8gYEFjdGl2YXRlZFJvdXRlYCBvcGNpb25hbCDihpIgbGEgdmlzdGEgZnVuY2lvbmEgZW1iZWJpZGEgLyBlbiBTdG9yeWJvb2sgc2luXG4gIC8vIHJvdXRlciAoc29sbyBsbyB1c2EgcGFyYSBsZWVyIGVsIHJvdXRlIGRhdGEgZGUgY29uZmlnIGNvbW8gZmFsbGJhY2spLiBMYVxuICAvLyBuYXZlZ2FjacOzbiB2YSBwb3IgYE5hdmlnYXRpb25TZXJ2aWNlYCAod3JhcHBlciBvcGNpb25hbCBzb2JyZSBgUm91dGVyYCkuXG4gIHByaXZhdGUgcm91dGUgPSBpbmplY3QoQWN0aXZhdGVkUm91dGUsIHsgb3B0aW9uYWw6IHRydWUgfSk7XG5cbiAgLyoqXG4gICAqIENvbmZpZyB2w61hIEBJbnB1dCAob2JqZWN0LWZpcnN0KS4gU2kgbm8gc2UgcGFzYSwgc2UgY2FlIGFsIHJvdXRlIGRhdGFcbiAgICogYG5vdGlmaWNhdGlvbnNDb25maWdgIChwb2JsYWRvIHBvciBgcHJvdmlkZVZhbHRlY2hOb3RpZmljYXRpb25zUm91dGVzYCkuXG4gICAqIGByZXNvbHZlZENvbmZpZ2AgbWVyZ2VhIGNvbiBsb3MgZGVmYXVsdHMg4oCUIGBASW5wdXRgIGdhbmEgc29icmUgcm91dGUgZGF0YS5cbiAgICovXG4gIEBJbnB1dCgpIGNvbmZpZz86IE5vdGlmaWNhdGlvbnNWaWV3Q29uZmlnO1xuXG4gIHJlYWRvbmx5IHJlc29sdmVkQ29uZmlnID0gY29tcHV0ZWQ8XG4gICAgUmVxdWlyZWQ8T21pdDxOb3RpZmljYXRpb25zVmlld0NvbmZpZywgJ29uTm90aWZpY2F0aW9uT3Blbic+PiAmIFBpY2s8Tm90aWZpY2F0aW9uc1ZpZXdDb25maWcsICdvbk5vdGlmaWNhdGlvbk9wZW4nPlxuICA+KCgpID0+IHtcbiAgICBjb25zdCBmcm9tUm91dGUgPSAodGhpcy5yb3V0ZT8uc25hcHNob3QuZGF0YVsnbm90aWZpY2F0aW9uc0NvbmZpZyddID8/IHt9KSBhcyBOb3RpZmljYXRpb25zVmlld0NvbmZpZztcbiAgICBjb25zdCBtZXJnZWQ6IE5vdGlmaWNhdGlvbnNWaWV3Q29uZmlnID0geyAuLi5mcm9tUm91dGUsIC4uLih0aGlzLmNvbmZpZyA/PyB7fSkgfTtcbiAgICByZXR1cm4ge1xuICAgICAgc2hvd1B1c2hPZmZDdGE6IG1lcmdlZC5zaG93UHVzaE9mZkN0YSA/PyB0cnVlLFxuICAgICAgZW5hYmxlTWFya0FsbDogbWVyZ2VkLmVuYWJsZU1hcmtBbGwgPz8gdHJ1ZSxcbiAgICAgIHNldHRpbmdzTm90aWZpY2F0aW9uc1BhdGg6IG1lcmdlZC5zZXR0aW5nc05vdGlmaWNhdGlvbnNQYXRoID8/IERFRkFVTFRfU0VUVElOR1NfUEFUSCxcbiAgICAgIGkxOG5OYW1lc3BhY2U6IG1lcmdlZC5pMThuTmFtZXNwYWNlID8/IERFRkFVTFRfTkFNRVNQQUNFLFxuICAgICAgcGFnZVNpemU6IG1lcmdlZC5wYWdlU2l6ZSA/PyBERUZBVUxUX1BBR0VfU0laRSxcbiAgICAgIG1heExvYWQ6IG1lcmdlZC5tYXhMb2FkID8/IERFRkFVTFRfTUFYX0xPQUQsXG4gICAgICBvbk5vdGlmaWNhdGlvbk9wZW46IG1lcmdlZC5vbk5vdGlmaWNhdGlvbk9wZW4sXG4gICAgfTtcbiAgfSk7XG5cbiAgLyoqIE5hbWVzcGFjZSBpMThuIHJlc3VlbHRvIChjYXB0dXJhZG8gcGFyYSBsbGFtYWRhcyBuby1yZWFjdGl2YXMpLiAqL1xuICBwcml2YXRlIGdldCBucygpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLnJlc29sdmVkQ29uZmlnKCkuaTE4bk5hbWVzcGFjZTtcbiAgfVxuXG4gIC8qKiBQYXNvIGRlIHBhZ2luYWNpw7NuIHNvZnQgKHJldmVsYSArTiBwb3IgXCJjYXJnYXIgbcOhc1wiKS4gKi9cbiAgcHJpdmF0ZSBnZXQgcGFnZVN0ZXAoKTogbnVtYmVyIHtcbiAgICByZXR1cm4gdGhpcy5yZXNvbHZlZENvbmZpZygpLnBhZ2VTaXplO1xuICB9XG5cbiAgcHJpdmF0ZSByZWFkb25seSBfZXhwYW5kZWQgPSBzaWduYWw8U2V0PHN0cmluZz4+KG5ldyBTZXQoKSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX3BhZ2VTaXplID0gc2lnbmFsKHRoaXMucmVzb2x2ZWRDb25maWcoKS5wYWdlU2l6ZSk7XG4gIHByaXZhdGUgcmVhZG9ubHkgX2J1bGtCdXN5ID0gc2lnbmFsKGZhbHNlKTtcbiAgcHJpdmF0ZSByZWFkb25seSBfbG9hZGluZ01vcmUgPSBzaWduYWwoZmFsc2UpO1xuXG4gIC8qKlxuICAgKiBQdXNoIGFjdGl2YWRvID0gcGVybWlzbyBkZWwgbmF2ZWdhZG9yIGVuIGBncmFudGVkYC4gU2kgTk8gZXN0w6EgYWN0aXZhZG8sXG4gICAqIGVsIHVzZXIgcHVlZGUgbGVlciBlbCBpbmJveCAoRmlyZXN0b3JlKSBwZXJvIE5PIHJlY2liaXLDoSBwdXNoIGVuIHN1XG4gICAqIGRpc3Bvc2l0aXZvIOKGkiBtb3N0cmFtb3MgdW5hIGNhcmQgcXVlIGxvIGludml0YSBhIGlyIGEgY29uZmlndXJhY2nDs24uXG4gICAqIFNlIGV2YWzDumEgZW4gY2FkYSBtb250YWplIGRlIGxhIHZpc3RhLlxuICAgKi9cbiAgcmVhZG9ubHkgcHVzaEVuYWJsZWQgPSBzaWduYWwodGhpcy5hdXRoLmdldE5vdGlmaWNhdGlvblBlcm1pc3Npb25TdGF0ZSgpID09PSAnZ3JhbnRlZCcpO1xuXG4gIC8qKlxuICAgKiBTdHJlYW0gZmlyZXN0b3JlIHJlYWwtdGltZSB2w61hIGVsIGhlbHBlciBlc3TDoW5kYXIgYGNyZWF0ZVJlZnJlc2hhYmxlU3RyZWFtYFxuICAgKiAobW9kbyByZWFsLXRpbWU6IGZhY3RvcnkgZGV2dWVsdmUgdW4gbGlzdGVuZXIgdml2byBgbm90aWZzLmdldEFsbChtYXhMb2FkKWApLlxuICAgKlxuICAgKiBFbCBoZWxwZXIgZ2F0ZWEgbGEgcHJpbWVyYSBzdXNjcmlwY2nDs24gcG9yIGBmaXJlYmFzZUF1dGhSZWFkeWAsIGFwbGljYSB1blxuICAgKiBgcmV0cnlgIGNvcnRvIGNvbiBiYWNrb2ZmIHksIHRyYXMgYWdvdGFyIHJlaW50ZW50b3MsIGVtaXRlIGVsIGZhbGxiYWNrIChgW11gKVxuICAgKiB5IG1hcmNhIGBlcnJvcmAg4oCUIGVzdGFkbyBkZSBlcnJvciBlbiBVSSwgbm8gc2tlbGV0b24gaW5maW5pdG8uIGByZWxvYWQoKWBcbiAgICogcmUtc3VzY3JpYmUgZWwgc3RyZWFtIGNvbXBsZXRvIChsbyB1c2EgZWwgcHVsbC10by1yZWZyZXNoKS5cbiAgICovXG4gIHByaXZhdGUgcmVhZG9ubHkgX3N0cmVhbSA9IGNyZWF0ZVJlZnJlc2hhYmxlU3RyZWFtPE5vdGlmaWNhdGlvbkRvY3VtZW50W10+KFxuICAgICgpID0+IHRoaXMubm90aWZzLmdldEFsbCh0aGlzLnJlc29sdmVkQ29uZmlnKCkubWF4TG9hZCksXG4gICAge1xuICAgICAgZmFsbGJhY2s6IFtdLFxuICAgICAgLy8gYG5vdGlmcy5nZXRBbGwoKWAgWUEgZ2F0ZWEgaW50ZXJuYW1lbnRlIHBvciBgZmlyZWJhc2VBdXRoUmVhZHlgLiBTaSBlbFxuICAgICAgLy8gc3RyZWFtIHRhbWJpw6luIGdhdGVhcmEsIHNlcsOtYW4gRE9TIGVzcGVyYXMgZGUgYXV0aCBhcGlsYWRhcy5cbiAgICAgIGdhdGVPbkZpcmViYXNlQXV0aDogZmFsc2UsXG4gICAgICAvLyBDb2xkIHN0YXJ0IGRlIFBXQSBlbiBpT1MgcHVlZGUgcGFzYXIgZGUgOHMgZW4gcmVkZXMgbGVudGFzOyBjb24gMTVzXG4gICAgICAvLyBldml0YW1vcyBlbCBmYWxzbyBlc3RhZG8gZGUgZXJyb3IuXG4gICAgICBmaXJzdEVtaXRUaW1lb3V0TXM6IDE1MDAwLFxuICAgIH1cbiAgKTtcblxuICAvKiogVHJ1ZSBzaSBlbCBzdHJlYW0gZmFsbMOzIHRyYXMgYWdvdGFyIHJlaW50ZW50b3Mg4oaSIG11ZXN0cmEgZXN0YWRvIGRlIGVycm9yLiAqL1xuICByZWFkb25seSBzdHJlYW1FcnJvciA9IHRoaXMuX3N0cmVhbS5lcnJvcjtcblxuICByZWFkb25seSBsb2FkaW5nID0gY29tcHV0ZWQoKCkgPT4gdGhpcy5fc3RyZWFtLmRhdGEoKSA9PT0gbnVsbCk7XG5cbiAgLyoqXG4gICAqIE5vdGlmcyByZWFsZXMgbW9zdHJhZGFzLiBGaWx0cmFtb3MgZG9jcyBzaW4gdMOtdHVsbyBZIHNpbiBib2R5IOKAlCBzb24gcnVpZG9cbiAgICogKHTDrXBpY2FtZW50ZSBzZW50aW5lbC9zeXN0ZW0gd3JpdGVzIHByZS1zY2hlbWEgY29uIHRpdGxlL2JvZHkgb3BjaW9uYWxlcykuXG4gICAqL1xuICByZWFkb25seSBhbGxOb3RpZnMgPSBjb21wdXRlZDxOb3RpZmljYXRpb25Eb2N1bWVudFtdPigoKSA9PlxuICAgICh0aGlzLl9zdHJlYW0uZGF0YSgpID8/IFtdKS5maWx0ZXIobiA9PiAhIShuLnRpdGxlICYmIG4udGl0bGUudHJpbSgpKSB8fCAhIShuLmJvZHkgJiYgbi5ib2R5LnRyaW0oKSkpXG4gICk7XG4gIHJlYWRvbmx5IGhhc01vcmUgPSBjb21wdXRlZCgoKSA9PiB0aGlzLmFsbE5vdGlmcygpLmxlbmd0aCA+IHRoaXMuX3BhZ2VTaXplKCkpO1xuICByZWFkb25seSBzaG93TWFya0FsbCA9IGNvbXB1dGVkKFxuICAgICgpID0+IHRoaXMucmVzb2x2ZWRDb25maWcoKS5lbmFibGVNYXJrQWxsICYmICF0aGlzLmxvYWRpbmcoKSAmJiB0aGlzLmFsbE5vdGlmcygpLnNvbWUobiA9PiAhbi5pc1JlYWQpXG4gICk7XG5cbiAgLyoqIFN1Yi1jb25qdW50byBwYWdpbmFkbywgYWdydXBhZG8gcG9yIHBlcsOtb2RvLiAqL1xuICByZWFkb25seSBncm91cHMgPSBjb21wdXRlZDxOb3RpZmljYXRpb25Hcm91cFtdPigoKSA9PiB7XG4gICAgY29uc3QgaXRlbXMgPSB0aGlzLmFsbE5vdGlmcygpLnNsaWNlKDAsIHRoaXMuX3BhZ2VTaXplKCkpO1xuICAgIGNvbnN0IG5vdyA9IG5ldyBEYXRlKCk7XG4gICAgY29uc3QgYnVja2V0czogUmVjb3JkPEdyb3VwS2V5LCBOb3RpZmljYXRpb25Eb2N1bWVudFtdPiA9IHtcbiAgICAgIHRvZGF5OiBbXSxcbiAgICAgIHRoaXNNb250aDogW10sXG4gICAgICBlYXJsaWVyOiBbXSxcbiAgICB9O1xuICAgIGZvciAoY29uc3QgbiBvZiBpdGVtcykge1xuICAgICAgYnVja2V0c1t0aGlzLmJ1Y2tldE9mKG4sIG5vdyldLnB1c2gobik7XG4gICAgfVxuICAgIGNvbnN0IG91dDogTm90aWZpY2F0aW9uR3JvdXBbXSA9IFtdO1xuICAgIGlmIChidWNrZXRzLnRvZGF5Lmxlbmd0aCkge1xuICAgICAgb3V0LnB1c2goeyBrZXk6ICd0b2RheScsIGxhYmVsOiB0aGlzLnR0KCdncm91cFRvZGF5JyksIGl0ZW1zOiBidWNrZXRzLnRvZGF5IH0pO1xuICAgIH1cbiAgICBpZiAoYnVja2V0cy50aGlzTW9udGgubGVuZ3RoKSB7XG4gICAgICBvdXQucHVzaCh7XG4gICAgICAgIGtleTogJ3RoaXNNb250aCcsXG4gICAgICAgIGxhYmVsOiB0aGlzLnR0KCdncm91cFRoaXNNb250aCcpLFxuICAgICAgICBpdGVtczogYnVja2V0cy50aGlzTW9udGgsXG4gICAgICB9KTtcbiAgICB9XG4gICAgaWYgKGJ1Y2tldHMuZWFybGllci5sZW5ndGgpIHtcbiAgICAgIG91dC5wdXNoKHsga2V5OiAnZWFybGllcicsIGxhYmVsOiB0aGlzLnR0KCdncm91cEVhcmxpZXInKSwgaXRlbXM6IGJ1Y2tldHMuZWFybGllciB9KTtcbiAgICB9XG4gICAgcmV0dXJuIG91dDtcbiAgfSk7XG5cbiAgcmVhZG9ubHkgcGFnZVRpdGxlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy50dCgncGFnZVRpdGxlJykpO1xuICByZWFkb25seSBwYWdlRGVzY3JpcHRpb24gPSBjb21wdXRlZCgoKSA9PiB0aGlzLnR0KCdwYWdlRGVzY3JpcHRpb24nKSk7XG5cbiAgLy8gQ1RBIFwiYWN0aXZhIGxhcyBub3RpZmljYWNpb25lcyBwdXNoXCIg4oCUIHZpc2libGUgY3VhbmRvIHB1c2hFbmFibGVkKCkgZXMgZmFsc2UuXG4gIHJlYWRvbmx5IGN0YVRpdGxlID0gY29tcHV0ZWQoKCkgPT4gdGhpcy50dCgncHVzaE9mZlRpdGxlJykpO1xuICByZWFkb25seSBjdGFIaW50ID0gY29tcHV0ZWQoKCkgPT4gdGhpcy50dCgncHVzaE9mZkhpbnQnKSk7XG4gIHJlYWRvbmx5IGN0YUJ1dHRvblByb3BzID0gY29tcHV0ZWQ8UGFydGlhbDxCdXR0b25NZXRhZGF0YT4+KCgpID0+ICh7XG4gICAgdGV4dDogdGhpcy50dCgncHVzaE9mZkN0YScpLFxuICAgIGNvbG9yOiAnZGFyaycsXG4gICAgZmlsbDogJ291dGxpbmUnLFxuICAgIHNpemU6ICdzbWFsbCcsXG4gICAgc2hhcGU6ICdyb3VuZCcsXG4gICAgdHlwZTogJ2J1dHRvbicsXG4gIH0pKTtcblxuICAvKipcbiAgICogRXN0YWRvIGRlIGVycm9yIGRlIGNhcmdhOiBjb252aWVydGUgZWwgZXJyb3IgZGVsIHN0cmVhbSBlblxuICAgKiBgRW1wdHlTdGF0ZU1ldGFkYXRhYCB2aWEgZWwgaGVscGVyIGNhbsOzbmljbyBgY3JlYXRlRXJyb3JTdGF0ZVByb3BzYC5cbiAgICogRWwgaGVscGVyIGRlY2lkZSB2YXJpYW50ZSAoYG9mZmxpbmVgIHZzIGBlcnJvcmApIHBvciBgaXNOZXR3b3JrYC5cbiAgICogTnVsbCBjdWFuZG8gZWwgc3RyZWFtIG5vIGhhIGZhbGxhZG8uXG4gICAqL1xuICByZWFkb25seSBlcnJvclN0YXRlID0gY29tcHV0ZWQ8RW1wdHlTdGF0ZU1ldGFkYXRhIHwgbnVsbD4oKCkgPT4ge1xuICAgIHRoaXMuaTE4bi5sYW5nKCk7XG4gICAgY29uc3QgZXJyID0gdGhpcy5zdHJlYW1FcnJvcigpO1xuICAgIGlmICghZXJyKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gY3JlYXRlRXJyb3JTdGF0ZVByb3BzKGVyciwge1xuICAgICAgdGl0bGU6IHtcbiAgICAgICAgb2ZmbGluZTogdGhpcy50dCgnb2ZmbGluZVRpdGxlJyksXG4gICAgICAgIGVycm9yOiB0aGlzLnR0KCdsb2FkRXJyb3JUaXRsZScpLFxuICAgICAgfSxcbiAgICAgIGRlc2NyaXB0aW9uOiB7XG4gICAgICAgIG9mZmxpbmU6IHRoaXMudHQoJ29mZmxpbmVIaW50JyksXG4gICAgICAgIGVycm9yOiBpbnRlcnByZXRFcnJvcihlcnIpLm1lc3NhZ2UgfHwgdGhpcy50dCgnbG9hZEVycm9ySGludCcpLFxuICAgICAgfSxcbiAgICAgIHJldHJ5TGFiZWw6IHRoaXMudHQoJ3JldHJ5Q3RhJyksXG4gICAgICBvblJldHJ5OiAoKSA9PiB0aGlzLl9zdHJlYW0ucmVsb2FkKCksXG4gICAgICByZXRyeWluZzogdGhpcy5sb2FkaW5nKCksXG4gICAgfSk7XG4gIH0pO1xuXG4gIC8qKlxuICAgKiBFc3RhZG8gdmFjw61vIChsaXN0YSByZWFsID0gMCBub3RpZmljYWNpb25lcywgc2luIGVycm9yIGRlIGNhcmdhKS5cbiAgICogU2UgY29uc3RydXllIG1hbnVhbG1lbnRlIGNvbiBgdmFyaWFudDogJ2VtcHR5J2Ag4oCUIHNpbiBoZWxwZXIgZGUgZXJyb3IuXG4gICAqL1xuICByZWFkb25seSBlbXB0eVN0YXRlUHJvcHMgPSBjb21wdXRlZDxFbXB0eVN0YXRlTWV0YWRhdGE+KCgpID0+IHtcbiAgICB0aGlzLmkxOG4ubGFuZygpO1xuICAgIHJldHVybiB7XG4gICAgICB2YXJpYW50OiAnZW1wdHknLFxuICAgICAgaWNvbjogJ25vdGlmaWNhdGlvbnMtb2ZmLW91dGxpbmUnLFxuICAgICAgdGl0bGU6IHRoaXMudHQoJ2VtcHR5JyksXG4gICAgICBkZXNjcmlwdGlvbjogdGhpcy50dCgnZW1wdHlIaW50JyksXG4gICAgICBhY3Rpb246IHtcbiAgICAgICAgbGFiZWw6IHRoaXMudHQoJ2VtcHR5Q3RhJyksXG4gICAgICAgIGhhbmRsZXI6ICgpID0+IHRoaXMub25Hb1RvU2V0dGluZ3MoKSxcbiAgICAgIH0sXG4gICAgfTtcbiAgfSk7XG5cbiAgcmVhZG9ubHkgc2VlTW9yZSA9IGNvbXB1dGVkKCgpID0+IHRoaXMudHQoJ3NlZU1vcmUnKSk7XG4gIHJlYWRvbmx5IHNlZUxlc3MgPSBjb21wdXRlZCgoKSA9PiB0aGlzLnR0KCdzZWVMZXNzJykpO1xuXG4gIHJlYWRvbmx5IG1hcmtBbGxCdXR0b25Qcm9wcyA9IGNvbXB1dGVkPFBhcnRpYWw8QnV0dG9uTWV0YWRhdGE+PigoKSA9PiAoe1xuICAgIHRleHQ6IHRoaXMudHQoJ21hcmtBbGwnKSxcbiAgICBjb2xvcjogJ2RhcmsnLFxuICAgIGZpbGw6ICdvdXRsaW5lJyxcbiAgICBzaXplOiAnc21hbGwnLFxuICAgIHNoYXBlOiAncm91bmQnLFxuICAgIHR5cGU6ICdidXR0b24nLFxuICAgIGljb246IHsgbmFtZTogJ2NoZWNrbWFyay1kb25lLW91dGxpbmUnLCBzbG90OiAnc3RhcnQnIH0sXG4gICAgc3RhdGU6IHRoaXMuX2J1bGtCdXN5KCkgPyBDb21wb25lbnRTdGF0ZXMuV09SS0lORyA6IENvbXBvbmVudFN0YXRlcy5FTkFCTEVELFxuICB9KSk7XG5cbiAgcmVhZG9ubHkgbG9hZE1vcmVCdXR0b25Qcm9wcyA9IGNvbXB1dGVkPFBhcnRpYWw8QnV0dG9uTWV0YWRhdGE+PigoKSA9PiAoe1xuICAgIHRleHQ6IHRoaXMudHQoJ2xvYWRNb3JlJyksXG4gICAgY29sb3I6ICdkYXJrJyxcbiAgICBmaWxsOiAnY2xlYXInLFxuICAgIHNpemU6ICdkZWZhdWx0JyxcbiAgICBzaGFwZTogJ3JvdW5kJyxcbiAgICB0eXBlOiAnYnV0dG9uJyxcbiAgICBzdGF0ZTogdGhpcy5fbG9hZGluZ01vcmUoKSA/IENvbXBvbmVudFN0YXRlcy5XT1JLSU5HIDogQ29tcG9uZW50U3RhdGVzLkVOQUJMRUQsXG4gIH0pKTtcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICBjb25zdCBucyA9IHRoaXMubnM7XG4gICAgaWYgKCF0aGlzLmkxOG4uaGFzTmFtZXNwYWNlKG5zKSkge1xuICAgICAgdGhpcy5pMThuLnJlZ2lzdGVyQ29udGVudChucywgTk9USUZJQ0FUSU9OU19WSUVXX0kxOE4pO1xuICAgIH1cbiAgICB0aGlzLm5hdi5zZXRCYWNrSGVhZGVyKCdwYWdlVGl0bGUnLCBucywgeyB3aXRoTWVudTogdHJ1ZSB9KTtcblxuICAgIC8vIFJlLWFwbGljYXIgaGVhZGVyIGVuIGNhbWJpbyBkZSBpZGlvbWEuXG4gICAgZWZmZWN0KFxuICAgICAgKCkgPT4ge1xuICAgICAgICB0aGlzLmkxOG4ubGFuZygpO1xuICAgICAgICB0aGlzLm5hdi5zZXRCYWNrSGVhZGVyKCdwYWdlVGl0bGUnLCB0aGlzLm5zLCB7IHdpdGhNZW51OiB0cnVlIH0pO1xuICAgICAgfSxcbiAgICAgIHsgYWxsb3dTaWduYWxXcml0ZXM6IHRydWUgfVxuICAgICk7XG4gIH1cblxuICAvKipcbiAgICogUmVnaXN0cmEgZWwgcHVsbC10by1yZWZyZXNoIGVzdMOhbmRhci4gVXNhbW9zIGBuZ09uSW5pdGAvYG5nT25EZXN0cm95YFxuICAgKiAoTk8gYGlvblZpZXdXaWxsRW50ZXJgKSBwb3JxdWUgYHZhbC1wYWdlLXdyYXBwZXJgIHVzYSBgPHJvdXRlci1vdXRsZXQ+YFxuICAgKiBwbGFubyDigJQgbG9zIGhvb2tzIGBpb25WaWV3KmAgc29sbyBkaXNwYXJhbiBkZW50cm8gZGUgYDxpb24tcm91dGVyLW91dGxldD5gLlxuICAgKi9cbiAgbmdPbkluaXQoKTogdm9pZCB7XG4gICAgdGhpcy5wYWdlUmVmcmVzaC5yZWdpc3RlcigoKSA9PiB0aGlzLnJlbG9hZCgpKTtcbiAgfVxuXG4gIC8qKiBRdWl0YSBlbCBoYW5kbGVyIGFsIGRlc3RydWlyIGxhIHZpc3RhIOKAlCBlbCByZWZyZXNoZXIgZGVzYXBhcmVjZS4gKi9cbiAgbmdPbkRlc3Ryb3koKTogdm9pZCB7XG4gICAgdGhpcy5wYWdlUmVmcmVzaC51bnJlZ2lzdGVyKCk7XG4gIH1cblxuICAvKipcbiAgICogUmVmcmVzaCBtYW51YWw6IHJlLXN1c2NyaWJlIGVsIHN0cmVhbSBGaXJlc3RvcmUgKGxpc3RlbmVyIG51ZXZvKSB2w61hIGVsXG4gICAqIGhlbHBlci4gUmVzdWVsdmUgdHJhcyB1biBtYXJnZW4gYnJldmUg4oCUIGVsIHN0cmVhbSBlcyByZWFsLXRpbWUgeSByZS1lbWl0ZVxuICAgKiBlbiBtaWxpc2VndW5kb3M7IGVsIGRlbGF5IHPDs2xvIG1hbnRpZW5lIGVsIHNwaW5uZXIgdmlzaWJsZSBsbyBqdXN0by5cbiAgICovXG4gIHByaXZhdGUgYXN5bmMgcmVsb2FkKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIHRoaXMuX3N0cmVhbS5yZWxvYWQoKTtcbiAgICBhd2FpdCBuZXcgUHJvbWlzZShyID0+IHNldFRpbWVvdXQociwgNzAwKSk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gUGVyLWl0ZW0gaGVscGVycyAocHVyb3Mg4oCUIHVzYWJsZXMgZGVzZGUgdGVtcGxhdGUpLlxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBvcGVuQnV0dG9uUHJvcHMoKTogUGFydGlhbDxCdXR0b25NZXRhZGF0YT4ge1xuICAgIHJldHVybiB7XG4gICAgICB0ZXh0OiB0aGlzLnR0KCdvcGVuJyksXG4gICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgZmlsbDogJ2NsZWFyJyxcbiAgICAgIHNpemU6ICdzbWFsbCcsXG4gICAgICBzaGFwZTogJ3JvdW5kJyxcbiAgICAgIHR5cGU6ICdidXR0b24nLFxuICAgICAgaWNvbjogeyBuYW1lOiAnb3Blbi1vdXRsaW5lJywgc2xvdDogJ2VuZCcgfSxcbiAgICB9O1xuICB9XG5cbiAgaXNFeHBhbmRlZChpZDogc3RyaW5nKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX2V4cGFuZGVkKCkuaGFzKGlkKTtcbiAgfVxuXG4gIHRvZ2dsZUV4cGFuZChpZDogc3RyaW5nKTogdm9pZCB7XG4gICAgY29uc3QgbmV4dCA9IG5ldyBTZXQodGhpcy5fZXhwYW5kZWQoKSk7XG4gICAgaWYgKG5leHQuaGFzKGlkKSkgbmV4dC5kZWxldGUoaWQpO1xuICAgIGVsc2UgbmV4dC5hZGQoaWQpO1xuICAgIHRoaXMuX2V4cGFuZGVkLnNldChuZXh0KTtcbiAgfVxuXG4gIGlzTG9uZyhib2R5OiBzdHJpbmcgfCB1bmRlZmluZWQpOiBib29sZWFuIHtcbiAgICBpZiAoIWJvZHkpIHJldHVybiBmYWxzZTtcbiAgICByZXR1cm4gYm9keS5sZW5ndGggPiAxMTAgfHwgYm9keS5pbmNsdWRlcygnXFxuJyk7XG4gIH1cblxuICAvKipcbiAgICogSWNvbiByZXNvbHZlciBjb24gb3JkZW4gZGUgZmFsbGJhY2s6XG4gICAqIDEuIG5vdGlmLnBheWxvYWQuaWNvbiAoZm9yd2FyZC1jb21wYXQsIHNpbiBicmVha2luZyBjaGFuZ2UgZW4gc2NoZW1hKVxuICAgKiAyLiBtYXBhIHBvciBub3RpZi50eXBlXG4gICAqIDMuIGRlZmF1bHQgbm90aWZpY2F0aW9ucy1vdXRsaW5lXG4gICAqL1xuICByZXNvbHZlSWNvbihuOiBOb3RpZmljYXRpb25Eb2N1bWVudCk6IFJlc29sdmVkSWNvbiB7XG4gICAgY29uc3QgaGludCA9IG4ucGF5bG9hZD8uWydpY29uJ10gYXMgSWNvbkhpbnQgfCB1bmRlZmluZWQ7XG4gICAgaWYgKGhpbnQ/LnZhbHVlKSB7XG4gICAgICBpZiAoaGludC50eXBlID09PSAnaW1hZ2UnIHx8IGhpbnQudHlwZSA9PT0gJ2F2YXRhcicpIHtcbiAgICAgICAgcmV0dXJuIHsga2luZDogaGludC50eXBlLCBzcmM6IGhpbnQudmFsdWUgfTtcbiAgICAgIH1cbiAgICAgIC8vIElnbm9yYW1vcyBoaW50LmNvbG9yIOKAlCB0b2RvcyBsb3MgaWNvbm9zIHZhbiBlbiBkYXJrIHBvciBjb252ZW5jacOzbiBVWC5cbiAgICAgIHJldHVybiB7IGtpbmQ6ICdpb25pY29uJywgbmFtZTogaGludC52YWx1ZSwgY29sb3I6ICdkYXJrJyB9O1xuICAgIH1cbiAgICBjb25zdCB0ID0gbi50eXBlO1xuICAgIGNvbnN0IG5hbWUgPSAoKCkgPT4ge1xuICAgICAgc3dpdGNoICh0KSB7XG4gICAgICAgIGNhc2UgJ2FwcHJvdmFsJzpcbiAgICAgICAgICByZXR1cm4gJ2NoZWNrbWFyay1jaXJjbGUtb3V0bGluZSc7XG4gICAgICAgIGNhc2UgJ2NoYXQnOlxuICAgICAgICBjYXNlICdjaGF0Ym90JzpcbiAgICAgICAgICByZXR1cm4gJ2NoYXRidWJibGUtb3V0bGluZSc7XG4gICAgICAgIGNhc2UgJ2NvbW1lbnQnOlxuICAgICAgICAgIHJldHVybiAnY2hhdGJveC1lbGxpcHNlcy1vdXRsaW5lJztcbiAgICAgICAgY2FzZSAncmVtaW5kZXInOlxuICAgICAgICAgIHJldHVybiAnYWxhcm0tb3V0bGluZSc7XG4gICAgICAgIGNhc2UgJ3N5c3RlbSc6XG4gICAgICAgICAgcmV0dXJuICdjb2ctb3V0bGluZSc7XG4gICAgICAgIGNhc2UgJ3VzZXInOlxuICAgICAgICBjYXNlICdtZW50aW9uJzpcbiAgICAgICAgICByZXR1cm4gJ3BlcnNvbi1vdXRsaW5lJztcbiAgICAgICAgY2FzZSAnZG9jdW1lbnQnOlxuICAgICAgICAgIHJldHVybiAnZG9jdW1lbnQtdGV4dC1vdXRsaW5lJztcbiAgICAgICAgZGVmYXVsdDpcbiAgICAgICAgICByZXR1cm4gJ25vdGlmaWNhdGlvbnMtb3V0bGluZSc7XG4gICAgICB9XG4gICAgfSkoKTtcbiAgICByZXR1cm4geyBraW5kOiAnaW9uaWNvbicsIG5hbWUsIGNvbG9yOiAnZGFyaycgfTtcbiAgfVxuXG4gIGlvbmljb25OYW1lKG46IE5vdGlmaWNhdGlvbkRvY3VtZW50KTogc3RyaW5nIHtcbiAgICBjb25zdCByID0gdGhpcy5yZXNvbHZlSWNvbihuKTtcbiAgICByZXR1cm4gci5raW5kID09PSAnaW9uaWNvbicgPyByLm5hbWUgOiAnJztcbiAgfVxuXG4gIGlvbmljb25Db2xvcihuOiBOb3RpZmljYXRpb25Eb2N1bWVudCk6IHN0cmluZyB8IHVuZGVmaW5lZCB7XG4gICAgY29uc3QgciA9IHRoaXMucmVzb2x2ZUljb24obik7XG4gICAgcmV0dXJuIHIua2luZCA9PT0gJ2lvbmljb24nID8gci5jb2xvciA6IHVuZGVmaW5lZDtcbiAgfVxuXG4gIGltYWdlU3JjKG46IE5vdGlmaWNhdGlvbkRvY3VtZW50KTogc3RyaW5nIHtcbiAgICBjb25zdCByID0gdGhpcy5yZXNvbHZlSWNvbihuKTtcbiAgICByZXR1cm4gci5raW5kID09PSAnaW1hZ2UnIHx8IHIua2luZCA9PT0gJ2F2YXRhcicgPyByLnNyYyA6ICcnO1xuICB9XG5cbiAgaW9uQ29sb3IodG9rZW46IHN0cmluZyB8IHVuZGVmaW5lZCk6IHN0cmluZyB7XG4gICAgaWYgKCF0b2tlbikgcmV0dXJuICd2YXIoLS1pb24tY29sb3ItcHJpbWFyeSknO1xuICAgIHJldHVybiBgdmFyKC0taW9uLWNvbG9yLSR7dG9rZW59KWA7XG4gIH1cblxuICByZWxhdGl2ZVRpbWUobjogTm90aWZpY2F0aW9uRG9jdW1lbnQpOiBzdHJpbmcge1xuICAgIGNvbnN0IGQgPSBuLmNyZWF0ZWRBdCBpbnN0YW5jZW9mIERhdGUgPyBuLmNyZWF0ZWRBdCA6IG51bGw7XG4gICAgaWYgKCFkKSByZXR1cm4gJyc7XG4gICAgY29uc3QgZGlmZk1zID0gRGF0ZS5ub3coKSAtIGQuZ2V0VGltZSgpO1xuICAgIGNvbnN0IG1pbiA9IE1hdGguZmxvb3IoZGlmZk1zIC8gNjAwMDApO1xuICAgIGlmIChtaW4gPCAxKSByZXR1cm4gdGhpcy50dCgndGltZU5vdycpO1xuICAgIGlmIChtaW4gPCA2MCkgcmV0dXJuIHRoaXMudHQoJ3RpbWVNaW51dGVzJykucmVwbGFjZSgne259JywgU3RyaW5nKG1pbikpO1xuICAgIGNvbnN0IGggPSBNYXRoLmZsb29yKG1pbiAvIDYwKTtcbiAgICBpZiAoaCA8IDI0KSByZXR1cm4gdGhpcy50dCgndGltZUhvdXJzJykucmVwbGFjZSgne259JywgU3RyaW5nKGgpKTtcbiAgICBjb25zdCBkYXlzID0gTWF0aC5mbG9vcihoIC8gMjQpO1xuICAgIHJldHVybiB0aGlzLnR0KCd0aW1lRGF5cycpLnJlcGxhY2UoJ3tufScsIFN0cmluZyhkYXlzKSk7XG4gIH1cblxuICAvKiogRGV2dWVsdmUgbGFiZWwgXCJEZXNkZSB7YXBwTmFtZX1cIiBzaSBsYSBub3RpZiB2aWVuZSBkZSBvdHJhIGFwcCwgc2lubyBudWxsLiAqL1xuICBzaG93Q3Jvc3NBcHBCYWRnZShuOiBOb3RpZmljYXRpb25Eb2N1bWVudCk6IHN0cmluZyB8IG51bGwge1xuICAgIGNvbnN0IGN1cnJlbnRBcHAgPSAnc2hvd2Nhc2UnO1xuICAgIGlmICghbi5hcHBJZCB8fCBuLmFwcElkID09PSBjdXJyZW50QXBwKSByZXR1cm4gbnVsbDtcbiAgICByZXR1cm4gdGhpcy50dCgnY3Jvc3NBcHAnKS5yZXBsYWNlKCd7YXBwfScsIG4uYXBwSWQpO1xuICB9XG5cbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG4gIC8vIEFjdGlvbnNcbiAgLy8gLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tXG5cbiAgYXN5bmMgb25PcGVuKG46IE5vdGlmaWNhdGlvbkRvY3VtZW50KTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdHJ5IHtcbiAgICAgIGNvbnN0IHJlc3VsdCA9IGF3YWl0IHRoaXMuYWN0aW9uLm9wZW4obik7XG4gICAgICB0aGlzLnJlc29sdmVkQ29uZmlnKCkub25Ob3RpZmljYXRpb25PcGVuPy4obiwgcmVzdWx0KTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIHRoaXMuZXJyb3JzLmhhbmRsZShlcnIsIHtcbiAgICAgICAgY29udGV4dDogJ25vdGlmaWNhdGlvbnMub3BlbicsXG4gICAgICAgIGZhbGxiYWNrS2V5OiAnb3BlbkVycm9yJyxcbiAgICAgICAgaTE4bk5hbWVzcGFjZTogdGhpcy5ucyxcbiAgICAgIH0pO1xuICAgIH1cbiAgfVxuXG4gIGFzeW5jIG9uTWFya0FsbCgpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICBpZiAodGhpcy5fYnVsa0J1c3koKSkgcmV0dXJuO1xuICAgIHRoaXMuX2J1bGtCdXN5LnNldCh0cnVlKTtcbiAgICB0cnkge1xuICAgICAgYXdhaXQgdGhpcy5ub3RpZnMubWFya0FsbEFzUmVhZCgpO1xuICAgICAgdGhpcy50b2FzdC5zaG93KHtcbiAgICAgICAgbWVzc2FnZTogdGhpcy50dCgnbWFya2VkQWxsU3VjY2VzcycpLFxuICAgICAgICBjb2xvcjogJ2RhcmsnLFxuICAgICAgICBkdXJhdGlvbjogMjUwMCxcbiAgICAgICAgcG9zaXRpb246ICd0b3AnLFxuICAgICAgfSk7XG4gICAgfSBjYXRjaCAoZXJyKSB7XG4gICAgICB0aGlzLmVycm9ycy5oYW5kbGUoZXJyLCB7XG4gICAgICAgIGNvbnRleHQ6ICdub3RpZmljYXRpb25zLm1hcmtBbGwnLFxuICAgICAgICBmYWxsYmFja0tleTogJ21hcmtlZEFsbEVycm9yJyxcbiAgICAgICAgaTE4bk5hbWVzcGFjZTogdGhpcy5ucyxcbiAgICAgIH0pO1xuICAgIH0gZmluYWxseSB7XG4gICAgICB0aGlzLl9idWxrQnVzeS5zZXQoZmFsc2UpO1xuICAgIH1cbiAgfVxuXG4gIG9uTG9hZE1vcmUoKTogdm9pZCB7XG4gICAgaWYgKHRoaXMuX2xvYWRpbmdNb3JlKCkpIHJldHVybjtcbiAgICB0aGlzLl9sb2FkaW5nTW9yZS5zZXQodHJ1ZSk7XG4gICAgLy8gU2xpY2UgdmllbmUgZGVsIGNhY2hlIGxvY2FsIOKAlCBubyBoYXkgZmV0Y2ggcmVhbCwgcGVybyB1biBicmV2ZSBzcGlubmVyXG4gICAgLy8gY29uZmlybWEgYWwgdXNlciBxdWUgZWwgY2xpY2sgcmVnaXN0csOzIHkgc3Vhdml6YSBsYSBhcGFyaWNpw7NuIGRlIGl0ZW1zLlxuICAgIHNldFRpbWVvdXQoKCkgPT4ge1xuICAgICAgdGhpcy5fcGFnZVNpemUudXBkYXRlKG4gPT4gbiArIHRoaXMucGFnZVN0ZXApO1xuICAgICAgdGhpcy5fbG9hZGluZ01vcmUuc2V0KGZhbHNlKTtcbiAgICB9LCAyNTApO1xuICB9XG5cbiAgb25Hb1RvU2V0dGluZ3MoKTogdm9pZCB7XG4gICAgdGhpcy5uYXYubmF2aWdhdGVCeVVybCh0aGlzLnJlc29sdmVkQ29uZmlnKCkuc2V0dGluZ3NOb3RpZmljYXRpb25zUGF0aCk7XG4gIH1cblxuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cbiAgLy8gR3JvdXBpbmcgaGVscGVyc1xuICAvLyAtLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS1cblxuICBwcml2YXRlIGJ1Y2tldE9mKG46IE5vdGlmaWNhdGlvbkRvY3VtZW50LCBub3c6IERhdGUpOiBHcm91cEtleSB7XG4gICAgY29uc3QgZCA9IG4uY3JlYXRlZEF0IGluc3RhbmNlb2YgRGF0ZSA/IG4uY3JlYXRlZEF0IDogbnVsbDtcbiAgICBpZiAoIWQpIHJldHVybiAnZWFybGllcic7XG4gICAgaWYgKGQuZ2V0RnVsbFllYXIoKSA9PT0gbm93LmdldEZ1bGxZZWFyKCkgJiYgZC5nZXRNb250aCgpID09PSBub3cuZ2V0TW9udGgoKSAmJiBkLmdldERhdGUoKSA9PT0gbm93LmdldERhdGUoKSkge1xuICAgICAgcmV0dXJuICd0b2RheSc7XG4gICAgfVxuICAgIGlmIChkLmdldEZ1bGxZZWFyKCkgPT09IG5vdy5nZXRGdWxsWWVhcigpICYmIGQuZ2V0TW9udGgoKSA9PT0gbm93LmdldE1vbnRoKCkpIHtcbiAgICAgIHJldHVybiAndGhpc01vbnRoJztcbiAgICB9XG4gICAgcmV0dXJuICdlYXJsaWVyJztcbiAgfVxuXG4gIHByaXZhdGUgdHQoa2V5OiBzdHJpbmcpOiBzdHJpbmcge1xuICAgIHJldHVybiB0aGlzLmkxOG4udChrZXksIHRoaXMubnMpO1xuICB9XG59XG4iXX0=
|