@idea-ionic/uncommon 8.2.1
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/LICENSE +373 -0
- package/README.md +21 -0
- package/css/global.scss +15 -0
- package/esm2022/idea-ionic-uncommon.mjs +5 -0
- package/esm2022/public-api.mjs +35 -0
- package/esm2022/src/AWSAPI.service.mjs +430 -0
- package/esm2022/src/AWSAPISocket.service.mjs +187 -0
- package/esm2022/src/address/address.component.mjs +94 -0
- package/esm2022/src/address/address.module.mjs +21 -0
- package/esm2022/src/announcement/announcement.component.mjs +41 -0
- package/esm2022/src/announcement/announcement.module.mjs +21 -0
- package/esm2022/src/cachedResources.service.mjs +55 -0
- package/esm2022/src/colors/colorPicker.component.mjs +135 -0
- package/esm2022/src/colors/colorPicker.module.mjs +20 -0
- package/esm2022/src/contacts/contacts.component.mjs +64 -0
- package/esm2022/src/contacts/contacts.module.mjs +21 -0
- package/esm2022/src/dateTime/calendarPicker.component.mjs +196 -0
- package/esm2022/src/dateTime/dateTime.component.mjs +133 -0
- package/esm2022/src/dateTime/dateTime.module.mjs +22 -0
- package/esm2022/src/duration/duration.component.mjs +77 -0
- package/esm2022/src/duration/duration.module.mjs +21 -0
- package/esm2022/src/echo/echo.module.mjs +26 -0
- package/esm2022/src/echo/echo.page.mjs +165 -0
- package/esm2022/src/errorReporting.service.mjs +68 -0
- package/esm2022/src/mde/mde.component.mjs +44 -0
- package/esm2022/src/mde/mde.module.mjs +22 -0
- package/esm2022/src/mde/mdeToolbar.component.mjs +12 -0
- package/esm2022/src/offline/cacheableResource.component.mjs +18 -0
- package/esm2022/src/offline/offline.module.mjs +22 -0
- package/esm2022/src/offline/offline.service.mjs +62 -0
- package/esm2022/src/offline/offlineData.service.mjs +479 -0
- package/esm2022/src/offline/offlineIndicator.component.mjs +58 -0
- package/esm2022/src/offline/offlineManager.component.mjs +84 -0
- package/esm2022/src/pushNotifications.service.mjs +56 -0
- package/esm2022/src/sentiment/sentiment.component.mjs +71 -0
- package/esm2022/src/sentiment/sentiment.module.mjs +21 -0
- package/esm2022/src/timeInterval/fromTimeToTime.component.mjs +155 -0
- package/esm2022/src/timeInterval/timeInterval.component.mjs +122 -0
- package/esm2022/src/timeInterval/timeInterval.module.mjs +22 -0
- package/esm2022/src/tinCan.service.mjs +49 -0
- package/fesm2022/idea-ionic-uncommon.mjs +2891 -0
- package/fesm2022/idea-ionic-uncommon.mjs.map +1 -0
- package/index.d.ts +5 -0
- package/package.json +51 -0
- package/public-api.d.ts +34 -0
- package/src/AWSAPI.service.d.ts +178 -0
- package/src/AWSAPISocket.service.d.ts +129 -0
- package/src/address/address.component.d.ts +64 -0
- package/src/address/address.module.d.ts +11 -0
- package/src/announcement/announcement.component.d.ts +23 -0
- package/src/announcement/announcement.module.d.ts +11 -0
- package/src/cachedResources.service.d.ts +34 -0
- package/src/colors/colorPicker.component.d.ts +78 -0
- package/src/colors/colorPicker.module.d.ts +10 -0
- package/src/contacts/contacts.component.d.ts +31 -0
- package/src/contacts/contacts.module.d.ts +11 -0
- package/src/dateTime/calendarPicker.component.d.ts +45 -0
- package/src/dateTime/dateTime.component.d.ts +81 -0
- package/src/dateTime/dateTime.module.d.ts +12 -0
- package/src/duration/duration.component.d.ts +68 -0
- package/src/duration/duration.module.d.ts +11 -0
- package/src/echo/echo.module.d.ts +12 -0
- package/src/echo/echo.page.d.ts +34 -0
- package/src/errorReporting.service.d.ts +26 -0
- package/src/mde/mde.component.d.ts +39 -0
- package/src/mde/mde.module.d.ts +12 -0
- package/src/mde/mdeToolbar.component.d.ts +5 -0
- package/src/offline/cacheableResource.component.d.ts +11 -0
- package/src/offline/offline.module.d.ts +12 -0
- package/src/offline/offline.service.d.ts +39 -0
- package/src/offline/offlineData.service.d.ts +281 -0
- package/src/offline/offlineIndicator.component.d.ts +25 -0
- package/src/offline/offlineManager.component.d.ts +17 -0
- package/src/pushNotifications.service.d.ts +26 -0
- package/src/sentiment/sentiment.component.d.ts +35 -0
- package/src/sentiment/sentiment.module.d.ts +11 -0
- package/src/timeInterval/fromTimeToTime.component.d.ts +61 -0
- package/src/timeInterval/timeInterval.component.d.ts +84 -0
- package/src/timeInterval/timeInterval.module.d.ts +12 -0
- package/src/tinCan.service.d.ts +31 -0
|
@@ -0,0 +1,479 @@
|
|
|
1
|
+
import { Injectable, inject } from '@angular/core';
|
|
2
|
+
import { IDEAStorageService, IDEATranslationsService } from '@idea-ionic/common';
|
|
3
|
+
import { IDEAAWSAPIService } from '../AWSAPI.service';
|
|
4
|
+
import { IDEAOfflineService } from './offline.service';
|
|
5
|
+
import * as i0 from "@angular/core";
|
|
6
|
+
/**
|
|
7
|
+
* After how much time we need to request a synchronisation to keep the contents up-to-date.
|
|
8
|
+
*/
|
|
9
|
+
export const SYNC_EXPIRATION_INTERVAL = 1000 * 60 * 60 * 24; // a day
|
|
10
|
+
/**
|
|
11
|
+
* Prefix for the key of the API requests queue info in the local storage.
|
|
12
|
+
*/
|
|
13
|
+
export const QUEUE_API_REQUESTS_KEY = 'IDEAOfflineService.queueAPIrequests';
|
|
14
|
+
/**
|
|
15
|
+
* Prefix for the key of the last sync time info in the local storage.
|
|
16
|
+
*/
|
|
17
|
+
export const LAST_SYNC_KEY = 'IDEAOfflineService.lastSyncAt';
|
|
18
|
+
/**
|
|
19
|
+
* The max number of elements per resource to synchronize during the first analysis of a synchronisation.
|
|
20
|
+
* If the number of elements exceeds (there is more data after the 1st page), the operation require manual confirmation.
|
|
21
|
+
*/
|
|
22
|
+
export const NUM_ELEMENTS_WITHOUT_MANUAL_SYNC = 100;
|
|
23
|
+
/**
|
|
24
|
+
* The max number of elements per resource to request at the same time during a normal synchronisation.
|
|
25
|
+
*/
|
|
26
|
+
export const NUM_ELEMENTS_WITH_MANUAL_SYNC = 300;
|
|
27
|
+
/**
|
|
28
|
+
* Manage the offline functioning of the app's data (upload/download/synchronization).
|
|
29
|
+
* Note: it includes all the methods of IDEAOfflineService.
|
|
30
|
+
*
|
|
31
|
+
* Download: it works through the **Delta** mechanism on back-end resources.
|
|
32
|
+
* Practically, the service prepares each possible API GET requests for each of the involved resources.
|
|
33
|
+
* In this way, if offline, the API service can hit an element by URL in the cache (storage offline).
|
|
34
|
+
*
|
|
35
|
+
* **How to use it**. Configure the sync mechanism in the main app.component as it follows:
|
|
36
|
+
*
|
|
37
|
+
* 1. Implement a CacheableResource class for each DeltaResource you want to cache offline.
|
|
38
|
+
* 2. Set up the service (`setUpOfflineData`).
|
|
39
|
+
* 3. Run a synchronization.
|
|
40
|
+
* 4. Add the navigation to the Offline Manager (UI).
|
|
41
|
+
* 5. Optionally, push offline API requests to the queue when offline.
|
|
42
|
+
*
|
|
43
|
+
* e.g. of CacheableResource classes:
|
|
44
|
+
* ```
|
|
45
|
+
* class CustomerCR extends CacheableResource {
|
|
46
|
+
* constructor(description: string) {
|
|
47
|
+
* super(DeltaResources.CUSTOMERS, description);
|
|
48
|
+
* }
|
|
49
|
+
* public listURL(element: any): string {
|
|
50
|
+
* return `teams/${element.teamId}/customers`;
|
|
51
|
+
* }
|
|
52
|
+
* public elementURL(element: any): string {
|
|
53
|
+
* return `teams/${element.teamId}/customers/${element.customerId}`;
|
|
54
|
+
* }
|
|
55
|
+
* public findIndexInList(list: Array<any>, element: any): number {
|
|
56
|
+
* return list.findIndex(x => x.customerId === element.customerId);
|
|
57
|
+
* }
|
|
58
|
+
* public sort(a: any, b: any): number {
|
|
59
|
+
* return a.name.localeCompare(b.name);
|
|
60
|
+
* }
|
|
61
|
+
* }
|
|
62
|
+
*/
|
|
63
|
+
export class IDEAOfflineDataService {
|
|
64
|
+
constructor() {
|
|
65
|
+
this._storage = inject(IDEAStorageService);
|
|
66
|
+
this._translate = inject(IDEATranslationsService);
|
|
67
|
+
this._offline = inject(IDEAOfflineService);
|
|
68
|
+
this._API = inject(IDEAAWSAPIService);
|
|
69
|
+
this.queueAPIRequests = new Array();
|
|
70
|
+
this.resources = new Array();
|
|
71
|
+
this.cacheableResources = {};
|
|
72
|
+
// subscribe to network changes
|
|
73
|
+
this._offline.subscribe(isOnline => {
|
|
74
|
+
if (isOnline) {
|
|
75
|
+
// try a synchronization if needed or if the last one failed
|
|
76
|
+
if (this.errorInLastSync)
|
|
77
|
+
this.synchronize();
|
|
78
|
+
else
|
|
79
|
+
this.synchronizeIfNeeded();
|
|
80
|
+
}
|
|
81
|
+
});
|
|
82
|
+
}
|
|
83
|
+
//
|
|
84
|
+
// NETWORK STATUS from IDEAOfflineService
|
|
85
|
+
//
|
|
86
|
+
/**
|
|
87
|
+
* Quickly check the connection status.
|
|
88
|
+
*/
|
|
89
|
+
isOnline() {
|
|
90
|
+
return this._offline.isOnline();
|
|
91
|
+
}
|
|
92
|
+
/**
|
|
93
|
+
* Quickly check the connection status.
|
|
94
|
+
*/
|
|
95
|
+
isOffline() {
|
|
96
|
+
return this._offline.isOffline();
|
|
97
|
+
}
|
|
98
|
+
/**
|
|
99
|
+
* Subscribe to the service to be notified when the connection status changes.
|
|
100
|
+
*/
|
|
101
|
+
subscribe(callback) {
|
|
102
|
+
return this._offline.subscribe(callback);
|
|
103
|
+
}
|
|
104
|
+
/**
|
|
105
|
+
* Quickly check for online connection.
|
|
106
|
+
*/
|
|
107
|
+
check() {
|
|
108
|
+
return this._offline.check();
|
|
109
|
+
}
|
|
110
|
+
//
|
|
111
|
+
// CONFIGURATION
|
|
112
|
+
//
|
|
113
|
+
/**
|
|
114
|
+
* Whether the offline mode is allowed. You can customize this function, if needed.
|
|
115
|
+
*/
|
|
116
|
+
isAllowed() {
|
|
117
|
+
return !!this.resources.length;
|
|
118
|
+
}
|
|
119
|
+
/**
|
|
120
|
+
* Set up the service to use and sync offline data.
|
|
121
|
+
*/
|
|
122
|
+
setUpOfflineData(teamId, useQueueAPIRequests, cacheableResources) {
|
|
123
|
+
// set the team
|
|
124
|
+
this.teamId = teamId;
|
|
125
|
+
// decide if to allow certain API request while offline
|
|
126
|
+
this.useQueueAPIRequests = useQueueAPIRequests;
|
|
127
|
+
// load the API request pending queue, if any
|
|
128
|
+
this.queueAPIRequestKey = this.teamId ? `${QUEUE_API_REQUESTS_KEY}_${this.teamId}` : QUEUE_API_REQUESTS_KEY;
|
|
129
|
+
this.loadQueueAPIRequest();
|
|
130
|
+
// load the lastSyncAt information for the team
|
|
131
|
+
this.lastSyncKey = this.teamId ? `${LAST_SYNC_KEY}_${this.teamId}` : LAST_SYNC_KEY;
|
|
132
|
+
this.loadLastSyncAt();
|
|
133
|
+
// load the cacheable resources
|
|
134
|
+
this.resources = new Array();
|
|
135
|
+
this.cacheableResources = {};
|
|
136
|
+
cacheableResources.forEach(r => this.addCacheableResource(r));
|
|
137
|
+
}
|
|
138
|
+
/**
|
|
139
|
+
* Load from the local storage the last sync at information.
|
|
140
|
+
*/
|
|
141
|
+
loadLastSyncAt() {
|
|
142
|
+
return new Promise(resolve => {
|
|
143
|
+
this._storage.get(this.lastSyncKey).then((lastSyncAt) => {
|
|
144
|
+
this.lastSyncAt = lastSyncAt ? Number(lastSyncAt) : null;
|
|
145
|
+
resolve(this.lastSyncAt);
|
|
146
|
+
});
|
|
147
|
+
});
|
|
148
|
+
}
|
|
149
|
+
/**
|
|
150
|
+
* Update last sync at info in the local storage.
|
|
151
|
+
*/
|
|
152
|
+
saveLastSyncAt(lastSyncAt) {
|
|
153
|
+
this.lastSyncAt = lastSyncAt;
|
|
154
|
+
return this._storage.set(this.lastSyncKey, lastSyncAt);
|
|
155
|
+
}
|
|
156
|
+
/**
|
|
157
|
+
* Add a CacheableResource.
|
|
158
|
+
*/
|
|
159
|
+
addCacheableResource(cacheableResource) {
|
|
160
|
+
if (this.teamId)
|
|
161
|
+
cacheableResource.teamId = this.teamId;
|
|
162
|
+
this.cacheableResources[cacheableResource.resource] = cacheableResource;
|
|
163
|
+
this.resources.push(cacheableResource.resource);
|
|
164
|
+
}
|
|
165
|
+
/**
|
|
166
|
+
* Remove a CacheableResource by its DeltaResource.
|
|
167
|
+
*/
|
|
168
|
+
removeCacheableResource(resource) {
|
|
169
|
+
delete this.cacheableResources[resource];
|
|
170
|
+
this.resources.splice(this.resources.indexOf(resource), 1);
|
|
171
|
+
}
|
|
172
|
+
/**
|
|
173
|
+
* Get the the DeltaResourced configured.
|
|
174
|
+
*/
|
|
175
|
+
getResources() {
|
|
176
|
+
return this.resources;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* Get a CacheableResource by its DeltaResource.
|
|
180
|
+
*/
|
|
181
|
+
getCacheableResource(resource) {
|
|
182
|
+
return this.cacheableResources[resource];
|
|
183
|
+
}
|
|
184
|
+
//
|
|
185
|
+
// UPLOAD
|
|
186
|
+
//
|
|
187
|
+
/**
|
|
188
|
+
* Execute all the API requests in the queue; the requests terminated with an error will remain in the queue.
|
|
189
|
+
*/
|
|
190
|
+
runQueueAPIRequests() {
|
|
191
|
+
return new Promise((resolve, reject) => {
|
|
192
|
+
if (!this.useQueueAPIRequests || this.isOffline() || !this.queueAPIRequests.length)
|
|
193
|
+
return resolve();
|
|
194
|
+
this.queueAPIRequests.forEach(async (request) => {
|
|
195
|
+
const options = {};
|
|
196
|
+
if (request.resourceId)
|
|
197
|
+
options.resourceId = request.resourceId;
|
|
198
|
+
if (request.body)
|
|
199
|
+
options.body = request.body;
|
|
200
|
+
let promise;
|
|
201
|
+
try {
|
|
202
|
+
switch (request.method.toUpperCase()) {
|
|
203
|
+
case 'POST':
|
|
204
|
+
promise = await this._API.postResource(request.resource, options);
|
|
205
|
+
break;
|
|
206
|
+
case 'PUT':
|
|
207
|
+
promise = await this._API.putResource(request.resource, options);
|
|
208
|
+
break;
|
|
209
|
+
case 'PATCH':
|
|
210
|
+
promise = await this._API.patchResource(request.resource, options);
|
|
211
|
+
break;
|
|
212
|
+
}
|
|
213
|
+
if (!promise)
|
|
214
|
+
request.error = 'INVALID_METHOD';
|
|
215
|
+
else
|
|
216
|
+
request.error = null;
|
|
217
|
+
}
|
|
218
|
+
catch (err) {
|
|
219
|
+
request.error = err.message || 'UNKNOWN_ERROR';
|
|
220
|
+
}
|
|
221
|
+
});
|
|
222
|
+
// keep the requests NOT successfully executed
|
|
223
|
+
this.saveQueueAPIRequest(this.queueAPIRequests.filter(x => x.error)).then(() => {
|
|
224
|
+
// if the queue is empty, the entire operation was successful
|
|
225
|
+
if (this.queueAPIRequests.length)
|
|
226
|
+
reject();
|
|
227
|
+
else
|
|
228
|
+
resolve();
|
|
229
|
+
});
|
|
230
|
+
});
|
|
231
|
+
}
|
|
232
|
+
/**
|
|
233
|
+
* Load from the local storage the API requests queue.
|
|
234
|
+
*/
|
|
235
|
+
loadQueueAPIRequest() {
|
|
236
|
+
return new Promise(resolve => {
|
|
237
|
+
if (!this.useQueueAPIRequests)
|
|
238
|
+
return resolve([]);
|
|
239
|
+
this._storage.get(this.queueAPIRequestKey).then((queue) => {
|
|
240
|
+
this.queueAPIRequests = queue || [];
|
|
241
|
+
resolve(this.queueAPIRequests);
|
|
242
|
+
});
|
|
243
|
+
});
|
|
244
|
+
}
|
|
245
|
+
/**
|
|
246
|
+
* Update the queue in memory and also save the copy in the local storage.
|
|
247
|
+
*/
|
|
248
|
+
saveQueueAPIRequest(queue) {
|
|
249
|
+
if (!this.isAllowed())
|
|
250
|
+
return Promise.reject();
|
|
251
|
+
this.queueAPIRequests = queue || this.queueAPIRequests;
|
|
252
|
+
return this._storage.set(this.queueAPIRequestKey, this.queueAPIRequests);
|
|
253
|
+
}
|
|
254
|
+
/**
|
|
255
|
+
* Delete a request stuck in an error.
|
|
256
|
+
*/
|
|
257
|
+
deleteRequest(request) {
|
|
258
|
+
if (!this.isAllowed())
|
|
259
|
+
return Promise.reject();
|
|
260
|
+
if (request) {
|
|
261
|
+
this.queueAPIRequests.splice(this.queueAPIRequests.indexOf(request), 1);
|
|
262
|
+
this.saveQueueAPIRequest();
|
|
263
|
+
}
|
|
264
|
+
}
|
|
265
|
+
//
|
|
266
|
+
// DOWNLOAD
|
|
267
|
+
//
|
|
268
|
+
/**
|
|
269
|
+
* Save the records of a delta and, if the latter has more pages, go recursive.
|
|
270
|
+
*/
|
|
271
|
+
async syncDeltaRecords(delta, done) {
|
|
272
|
+
// for each resource, we reset the status; if a resource still need to be synchronized, it will be flagged below
|
|
273
|
+
this.resources.forEach(resource => {
|
|
274
|
+
this.cacheableResources[resource].error = false;
|
|
275
|
+
this.cacheableResources[resource].synchronizing = false;
|
|
276
|
+
});
|
|
277
|
+
try {
|
|
278
|
+
// synchronze each of the resources included in the delta; this execution can go in parallel
|
|
279
|
+
await Promise.all(delta.resources.map(async (resource) => {
|
|
280
|
+
const cr = this.cacheableResources[resource];
|
|
281
|
+
if (cr) {
|
|
282
|
+
// synchronize the delta records; note: the executuion inside a resource must go in series
|
|
283
|
+
cr.synchronizing = true;
|
|
284
|
+
const success = await this.syncResourceDeltaRecords(resource, delta.records[resource]);
|
|
285
|
+
if (!success)
|
|
286
|
+
this.errorInLastSync = true;
|
|
287
|
+
}
|
|
288
|
+
}));
|
|
289
|
+
// if there were error of if there is nothing left to sync, we are done
|
|
290
|
+
if (this.errorInLastSync || !delta.next)
|
|
291
|
+
return done();
|
|
292
|
+
// otherwise, get the next page of the delta and go recursive until we are done
|
|
293
|
+
const params = { next: delta.next, limit: NUM_ELEMENTS_WITH_MANUAL_SYNC };
|
|
294
|
+
if (this.lastSyncAt)
|
|
295
|
+
params.since = this.lastSyncAt;
|
|
296
|
+
const newDelta = await this._API.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params });
|
|
297
|
+
this.syncDeltaRecords(newDelta, done);
|
|
298
|
+
}
|
|
299
|
+
catch (err) {
|
|
300
|
+
// if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
|
|
301
|
+
this.errorInLastSync = true;
|
|
302
|
+
return done();
|
|
303
|
+
}
|
|
304
|
+
}
|
|
305
|
+
/**
|
|
306
|
+
* Save offline a list of DeltaRecords for this resource, creating a map of all the corresponding API GET requests.
|
|
307
|
+
*/
|
|
308
|
+
async syncResourceDeltaRecords(resource, records) {
|
|
309
|
+
// acquire the info an a cacheable resource
|
|
310
|
+
const cr = this.cacheableResources[resource];
|
|
311
|
+
if (!cr)
|
|
312
|
+
return Promise.resolve(true);
|
|
313
|
+
try {
|
|
314
|
+
// prepare helpers to group executions of elements of the same list
|
|
315
|
+
let list = null, oldListURL = null;
|
|
316
|
+
for (const r of records) {
|
|
317
|
+
// calculate the URL to access the API request key for this element
|
|
318
|
+
const elementURL = cr.elementURL(r.element);
|
|
319
|
+
// if the element was deleted (based on delta), delete its corresponding API GET request
|
|
320
|
+
if (r.deleted)
|
|
321
|
+
await this._API.deleteFromCache(elementURL);
|
|
322
|
+
// otherwise, update it
|
|
323
|
+
else
|
|
324
|
+
await this._API.putInCache(elementURL, r.element);
|
|
325
|
+
// calculate the URLs to access the API request key for this element's list
|
|
326
|
+
const listURL = cr.listURL(r.element);
|
|
327
|
+
// to improve the performance, get/sort/save the list only when it changes from the previous element's one.
|
|
328
|
+
if (listURL !== oldListURL) {
|
|
329
|
+
// skip first cycle (oldListURL === null)
|
|
330
|
+
if (oldListURL) {
|
|
331
|
+
// re-sort the list; note: it should be sorted from the last time, so we only manage the new element
|
|
332
|
+
list = list.sort(cr.sort);
|
|
333
|
+
// save the updated list
|
|
334
|
+
await this._API.putInCache(oldListURL, list);
|
|
335
|
+
}
|
|
336
|
+
// get the list of elements from the local storage by the calculated URL
|
|
337
|
+
list = await this._API.getFromCache(listURL);
|
|
338
|
+
// save the reference to the list for the next cycle
|
|
339
|
+
oldListURL = listURL;
|
|
340
|
+
}
|
|
341
|
+
// find in the list the element we want to manage
|
|
342
|
+
const index = cr.findIndexInList(list, r.element);
|
|
343
|
+
// delete the element from the list
|
|
344
|
+
if (index !== -1)
|
|
345
|
+
list.splice(index, 1);
|
|
346
|
+
// if the element wasn't deleted (following the delta record information), insert the new version
|
|
347
|
+
if (!r.deleted)
|
|
348
|
+
list.push(r.element);
|
|
349
|
+
}
|
|
350
|
+
// in case there were elements, save the last element's list
|
|
351
|
+
if (oldListURL) {
|
|
352
|
+
// re-sort the list; note: it should be sorted from the last time, so we only manage the new element
|
|
353
|
+
list = list.sort(cr.sort);
|
|
354
|
+
// save the updated list
|
|
355
|
+
await this._API.putInCache(oldListURL, list);
|
|
356
|
+
}
|
|
357
|
+
return Promise.resolve(true);
|
|
358
|
+
}
|
|
359
|
+
catch (err) {
|
|
360
|
+
// if something went wrong, stops the operation, since we need to make sure the entire flow is consistent
|
|
361
|
+
cr.error = true;
|
|
362
|
+
return Promise.resolve(false);
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
//
|
|
366
|
+
// SYNCHRONISATION (UPLOAD+DOWNLOAD)
|
|
367
|
+
//
|
|
368
|
+
/**
|
|
369
|
+
* Run a sync, but only if needed, i.e. the cached content expired or we have pending API requests in the queue.
|
|
370
|
+
*/
|
|
371
|
+
synchronizeIfNeeded() {
|
|
372
|
+
return new Promise((resolve, reject) => {
|
|
373
|
+
if (!this.isAllowed())
|
|
374
|
+
return;
|
|
375
|
+
this.loadLastSyncAt().then(() => this.loadQueueAPIRequest()
|
|
376
|
+
.then(() => {
|
|
377
|
+
if (this.queueAPIRequests.length || Date.now() > this.lastSyncAt + SYNC_EXPIRATION_INTERVAL)
|
|
378
|
+
this.synchronize();
|
|
379
|
+
resolve();
|
|
380
|
+
})
|
|
381
|
+
.catch(err => reject(err)));
|
|
382
|
+
});
|
|
383
|
+
}
|
|
384
|
+
/**
|
|
385
|
+
* Synchronization of the whole set of resources (upload+download).
|
|
386
|
+
* @param manualConfirmation if true, the request comes directly from a user action (not automatic procedures).
|
|
387
|
+
*/
|
|
388
|
+
synchronize(manualConfirmation) {
|
|
389
|
+
return new Promise((resolve, reject) => {
|
|
390
|
+
if (!this.isAllowed() || this.synchronizing)
|
|
391
|
+
return resolve();
|
|
392
|
+
this.synchronizing = true;
|
|
393
|
+
this.errorInLastSync = false;
|
|
394
|
+
this.requiresManualConfirmation = false;
|
|
395
|
+
// load the lastSyncAt information
|
|
396
|
+
this.loadLastSyncAt().then(() =>
|
|
397
|
+
// try to run all the pending API requests in the queue, i.e. uploading the offline resources changed
|
|
398
|
+
this.runQueueAPIRequests()
|
|
399
|
+
.then(() => {
|
|
400
|
+
// set this moment in time: if anything happened before the end of the sync, we don't lose fresh data
|
|
401
|
+
const now = Date.now();
|
|
402
|
+
// prepare a first "short" Delta request, to see if there is a lot of data to process
|
|
403
|
+
const params = { limit: NUM_ELEMENTS_WITHOUT_MANUAL_SYNC };
|
|
404
|
+
if (this.lastSyncAt)
|
|
405
|
+
params.since = this.lastSyncAt;
|
|
406
|
+
this._API
|
|
407
|
+
.getResource(this.teamId ? `teams/${this.teamId}/delta` : 'delta', { params })
|
|
408
|
+
.then((delta) => {
|
|
409
|
+
// decide if to proceed with the sync: in case there is another page, it requires a manual confirmation
|
|
410
|
+
if (delta.next && !manualConfirmation) {
|
|
411
|
+
this.requiresManualConfirmation = true;
|
|
412
|
+
this.synchronizing = false;
|
|
413
|
+
return resolve();
|
|
414
|
+
}
|
|
415
|
+
// save the records in the delta and request possible new pages
|
|
416
|
+
this.syncDeltaRecords(delta, () => {
|
|
417
|
+
if (this.errorInLastSync) {
|
|
418
|
+
this.synchronizing = false;
|
|
419
|
+
resolve();
|
|
420
|
+
}
|
|
421
|
+
else {
|
|
422
|
+
// all the resources are succesfully in sync
|
|
423
|
+
this.resources.forEach(resource => (this.cacheableResources[resource].synchronizing = false));
|
|
424
|
+
// update the timestamp of last sync
|
|
425
|
+
this.saveLastSyncAt(now)
|
|
426
|
+
.then(() => {
|
|
427
|
+
this.synchronizing = false;
|
|
428
|
+
resolve();
|
|
429
|
+
})
|
|
430
|
+
.catch(() => {
|
|
431
|
+
// we couldn't save the last sync info
|
|
432
|
+
this.errorInLastSync = true;
|
|
433
|
+
this.synchronizing = false;
|
|
434
|
+
reject();
|
|
435
|
+
});
|
|
436
|
+
}
|
|
437
|
+
});
|
|
438
|
+
})
|
|
439
|
+
.catch(() => {
|
|
440
|
+
// we couldn't acquire new information (Delta)
|
|
441
|
+
this.errorInLastSync = true;
|
|
442
|
+
this.synchronizing = false;
|
|
443
|
+
reject();
|
|
444
|
+
});
|
|
445
|
+
})
|
|
446
|
+
.catch(() => {
|
|
447
|
+
// we stop, since we don't want backend data to override local info not yet uploaded
|
|
448
|
+
this.errorInLastSync = true;
|
|
449
|
+
this.synchronizing = false;
|
|
450
|
+
reject();
|
|
451
|
+
}));
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
/**
|
|
455
|
+
* Force a full synchronisation.
|
|
456
|
+
*/
|
|
457
|
+
forceFullSync() {
|
|
458
|
+
this._storage.clear().then(() => this.synchronize(true));
|
|
459
|
+
}
|
|
460
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineDataService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); }
|
|
461
|
+
static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineDataService }); }
|
|
462
|
+
}
|
|
463
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineDataService, decorators: [{
|
|
464
|
+
type: Injectable
|
|
465
|
+
}], ctorParameters: () => [] });
|
|
466
|
+
/**
|
|
467
|
+
* The abstract class to implement for each resource to cache offline from the back-end (DOWNLOAD).
|
|
468
|
+
*/
|
|
469
|
+
export class CacheableResource {
|
|
470
|
+
constructor(resource, description) {
|
|
471
|
+
this.resource = resource;
|
|
472
|
+
this.description = description;
|
|
473
|
+
this.synchronizing = false;
|
|
474
|
+
this.error = false;
|
|
475
|
+
// loaded at runtime
|
|
476
|
+
this.teamId = null;
|
|
477
|
+
}
|
|
478
|
+
}
|
|
479
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2ZmbGluZURhdGEuc2VydmljZS5qcyIsInNvdXJjZVJvb3QiOiIiLCJzb3VyY2VzIjpbIi4uLy4uLy4uLy4uLy4uL21vZHVsZXMvdW5jb21tb24vc3JjL29mZmxpbmUvb2ZmbGluZURhdGEuc2VydmljZS50cyJdLCJuYW1lcyI6W10sIm1hcHBpbmdzIjoiQUFBQSxPQUFPLEVBQUUsVUFBVSxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUduRCxPQUFPLEVBQUUsa0JBQWtCLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUVqRixPQUFPLEVBQUUsaUJBQWlCLEVBQW9CLE1BQU0sbUJBQW1CLENBQUM7QUFDeEUsT0FBTyxFQUFFLGtCQUFrQixFQUFFLE1BQU0sbUJBQW1CLENBQUM7O0FBRXZEOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sd0JBQXdCLEdBQUcsSUFBSSxHQUFHLEVBQUUsR0FBRyxFQUFFLEdBQUcsRUFBRSxDQUFDLENBQUMsUUFBUTtBQUNyRTs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLHNCQUFzQixHQUFHLHFDQUFxQyxDQUFDO0FBQzVFOztHQUVHO0FBQ0gsTUFBTSxDQUFDLE1BQU0sYUFBYSxHQUFHLCtCQUErQixDQUFDO0FBQzdEOzs7R0FHRztBQUNILE1BQU0sQ0FBQyxNQUFNLGdDQUFnQyxHQUFHLEdBQUcsQ0FBQztBQUNwRDs7R0FFRztBQUNILE1BQU0sQ0FBQyxNQUFNLDZCQUE2QixHQUFHLEdBQUcsQ0FBQztBQUVqRDs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7Ozs7R0FtQ0c7QUFFSCxNQUFNLE9BQU8sc0JBQXNCO0lBcURqQztRQXBEVSxhQUFRLEdBQUcsTUFBTSxDQUFDLGtCQUFrQixDQUFDLENBQUM7UUFDdEMsZUFBVSxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQzdDLGFBQVEsR0FBRyxNQUFNLENBQUMsa0JBQWtCLENBQUMsQ0FBQztRQUN0QyxTQUFJLEdBQUcsTUFB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MkZBQXRCLHNCQUFzQjtrQkFEbEMsVUFBVTs7QUFxZFg7O0dBRUc7QUFDSCxNQUFNLE9BQWdCLGlCQUFpQjtJQXVCckMsWUFBWSxRQUFnQixFQUFFLFdBQW1CO1FBQy9DLElBQUksQ0FBQyxRQUFRLEdBQUcsUUFBUSxDQUFDO1FBQ3pCLElBQUksQ0FBQyxXQUFXLEdBQUcsV0FBVyxDQUFDO1FBQy9CLElBQUksQ0FBQyxhQUFhLEdBQUcsS0FBSyxDQUFDO1FBQzNCLElBQUksQ0FBQyxLQUFLLEdBQUcsS0FBSyxDQUFDO1FBQ25CLG9CQUFvQjtRQUNwQixJQUFJLENBQUMsTUFBTSxHQUFHLElBQUksQ0FBQztJQUNyQixDQUFDO0NBc0JGIiwic291cmNlc0NvbnRlbnQiOlsiaW1wb3J0IHsgSW5qZWN0YWJsZSwgaW5qZWN0IH0gZnJvbSAnQGFuZ3VsYXIvY29yZSc7XG5pbXBvcnQgeyBTdWJzY3JpcHRpb24gfSBmcm9tICdyeGpzJztcbmltcG9ydCB7IERlbHRhLCBEZWx0YVJlY29yZCwgRGVsdGFSZXNvdXJjZXMsIGVwb2NoRGF0ZVRpbWUgfSBmcm9tICdpZGVhLXRvb2xib3gnO1xuaW1wb3J0IHsgSURFQVN0b3JhZ2VTZXJ2aWNlLCBJREVBVHJhbnNsYXRpb25zU2VydmljZSB9IGZyb20gJ0BpZGVhLWlvbmljL2NvbW1vbic7XG5cbmltcG9ydCB7IElERUFBV1NBUElTZXJ2aWNlLCBBUElSZXF1ZXN0T3B0aW9uIH0gZnJvbSAnLi4vQVdTQVBJLnNlcnZpY2UnO1xuaW1wb3J0IHsgSURFQU9mZmxpbmVTZXJ2aWNlIH0gZnJvbSAnLi9vZmZsaW5lLnNlcnZpY2UnO1xuXG4vKipcbiAqIEFmdGVyIGhvdyBtdWNoIHRpbWUgd2UgbmVlZCB0byByZXF1ZXN0IGEgc3luY2hyb25pc2F0aW9uIHRvIGtlZXAgdGhlIGNvbnRlbnRzIHVwLXRvLWRhdGUuXG4gKi9cbmV4cG9ydCBjb25zdCBTWU5DX0VYUElSQVRJT05fSU5URVJWQUwgPSAxMDAwICogNjAgKiA2MCAqIDI0OyAvLyBhIGRheVxuLyoqXG4gKiBQcmVmaXggZm9yIHRoZSBrZXkgb2YgdGhlIEFQSSByZXF1ZXN0cyBxdWV1ZSBpbmZvIGluIHRoZSBsb2NhbCBzdG9yYWdlLlxuICovXG5leHBvcnQgY29uc3QgUVVFVUVfQVBJX1JFUVVFU1RTX0tFWSA9ICdJREVBT2ZmbGluZVNlcnZpY2UucXVldWVBUElyZXF1ZXN0cyc7XG4vKipcbiAqIFByZWZpeCBmb3IgdGhlIGtleSBvZiB0aGUgbGFzdCBzeW5jIHRpbWUgaW5mbyBpbiB0aGUgbG9jYWwgc3RvcmFnZS5cbiAqL1xuZXhwb3J0IGNvbnN0IExBU1RfU1lOQ19LRVkgPSAnSURFQU9mZmxpbmVTZXJ2aWNlLmxhc3RTeW5jQXQnO1xuLyoqXG4gKiBUaGUgbWF4IG51bWJlciBvZiBlbGVtZW50cyBwZXIgcmVzb3VyY2UgdG8gc3luY2hyb25pemUgZHVyaW5nIHRoZSBmaXJzdCBhbmFseXNpcyBvZiBhIHN5bmNocm9uaXNhdGlvbi5cbiAqIElmIHRoZSBudW1iZXIgb2YgZWxlbWVudHMgZXhjZWVkcyAodGhlcmUgaXMgbW9yZSBkYXRhIGFmdGVyIHRoZSAxc3QgcGFnZSksIHRoZSBvcGVyYXRpb24gcmVxdWlyZSBtYW51YWwgY29uZmlybWF0aW9uLlxuICovXG5leHBvcnQgY29uc3QgTlVNX0VMRU1FTlRTX1dJVEhPVVRfTUFOVUFMX1NZTkMgPSAxMDA7XG4vKipcbiAqIFRoZSBtYXggbnVtYmVyIG9mIGVsZW1lbnRzIHBlciByZXNvdXJjZSB0byByZXF1ZXN0IGF0IHRoZSBzYW1lIHRpbWUgZHVyaW5nIGEgbm9ybWFsIHN5bmNocm9uaXNhdGlvbi5cbiAqL1xuZXhwb3J0IGNvbnN0IE5VTV9FTEVNRU5UU19XSVRIX01BTlVBTF9TWU5DID0gMzAwO1xuXG4vKipcbiAqIE1hbmFnZSB0aGUgb2ZmbGluZSBmdW5jdGlvbmluZyBvZiB0aGUgYXBwJ3MgZGF0YSAodXBsb2FkL2Rvd25sb2FkL3N5bmNocm9uaXphdGlvbikuXG4gKiBOb3RlOiBpdCBpbmNsdWRlcyBhbGwgdGhlIG1ldGhvZHMgb2YgSURFQU9mZmxpbmVTZXJ2aWNlLlxuICpcbiAqIERvd25sb2FkOiBpdCB3b3JrcyB0aHJvdWdoIHRoZSAqKkRlbHRhKiogbWVjaGFuaXNtIG9uIGJhY2stZW5kIHJlc291cmNlcy5cbiAqIFByYWN0aWNhbGx5LCB0aGUgc2VydmljZSBwcmVwYXJlcyBlYWNoIHBvc3NpYmxlIEFQSSBHRVQgcmVxdWVzdHMgZm9yIGVhY2ggb2YgdGhlIGludm9sdmVkIHJlc291cmNlcy5cbiAqIEluIHRoaXMgd2F5LCBpZiBvZmZsaW5lLCB0aGUgQVBJIHNlcnZpY2UgY2FuIGhpdCBhbiBlbGVtZW50IGJ5IFVSTCBpbiB0aGUgY2FjaGUgKHN0b3JhZ2Ugb2ZmbGluZSkuXG4gKlxuICogKipIb3cgdG8gdXNlIGl0KiouIENvbmZpZ3VyZSB0aGUgc3luYyBtZWNoYW5pc20gaW4gdGhlIG1haW4gYXBwLmNvbXBvbmVudCBhcyBpdCBmb2xsb3dzOlxuICpcbiAqICAgIDEuIEltcGxlbWVudCBhIENhY2hlYWJsZVJlc291cmNlIGNsYXNzIGZvciBlYWNoIERlbHRhUmVzb3VyY2UgeW91IHdhbnQgdG8gY2FjaGUgb2ZmbGluZS5cbiAqICAgIDIuIFNldCB1cCB0aGUgc2VydmljZSAoYHNldFVwT2ZmbGluZURhdGFgKS5cbiAqICAgIDMuIFJ1biBhIHN5bmNocm9uaXphdGlvbi5cbiAqICAgIDQuIEFkZCB0aGUgbmF2aWdhdGlvbiB0byB0aGUgT2ZmbGluZSBNYW5hZ2VyIChVSSkuXG4gKiAgICA1LiBPcHRpb25hbGx5LCBwdXNoIG9mZmxpbmUgQVBJIHJlcXVlc3RzIHRvIHRoZSBxdWV1ZSB3aGVuIG9mZmxpbmUuXG4gKlxuICogZS5nLiBvZiBDYWNoZWFibGVSZXNvdXJjZSBjbGFzc2VzOlxuICogYGBgXG4gKiBjbGFzcyBDdXN0b21lckNSIGV4dGVuZHMgQ2FjaGVhYmxlUmVzb3VyY2Uge1xuICogICBjb25zdHJ1Y3RvcihkZXNjcmlwdGlvbjogc3RyaW5nKSB7XG4gKiAgICAgc3VwZXIoRGVsdGFSZXNvdXJjZXMuQ1VTVE9NRVJTLCBkZXNjcmlwdGlvbik7XG4gKiAgIH1cbiAqICAgcHVibGljIGxpc3RVUkwoZWxlbWVudDogYW55KTogc3RyaW5nIHtcbiAqICAgICByZXR1cm4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVyc2A7XG4gKiAgIH1cbiAqICAgcHVibGljIGVsZW1lbnRVUkwoZWxlbWVudDogYW55KTogc3RyaW5nIHtcbiAqICAgICByZXR1cm4gYHRlYW1zLyR7ZWxlbWVudC50ZWFtSWR9L2N1c3RvbWVycy8ke2VsZW1lbnQuY3VzdG9tZXJJZH1gO1xuICogICB9XG4gKiAgIHB1YmxpYyBmaW5kSW5kZXhJbkxpc3QobGlzdDogQXJyYXk8YW55PiwgZWxlbWVudDogYW55KTogbnVtYmVyIHtcbiAqICAgICByZXR1cm4gbGlzdC5maW5kSW5kZXgoeCA9PiB4LmN1c3RvbWVySWQgPT09IGVsZW1lbnQuY3VzdG9tZXJJZCk7XG4gKiAgIH1cbiAqICAgcHVibGljIHNvcnQoYTogYW55LCBiOiBhbnkpOiBudW1iZXIge1xuICogICAgIHJldHVybiBhLm5hbWUubG9jYWxlQ29tcGFyZShiLm5hbWUpO1xuICogICB9XG4gKiB9XG4gKi9cbkBJbmplY3RhYmxlKClcbmV4cG9ydCBjbGFzcyBJREVBT2ZmbGluZURhdGFTZXJ2aWNlIHtcbiAgcHJvdGVjdGVkIF9zdG9yYWdlID0gaW5qZWN0KElERUFTdG9yYWdlU2VydmljZSk7XG4gIHByb3RlY3RlZCBfdHJhbnNsYXRlID0gaW5qZWN0KElERUFUcmFuc2xhdGlvbnNTZXJ2aWNlKTtcbiAgcHJvdGVjdGVkIF9vZmZsaW5lID0gaW5qZWN0KElERUFPZmZsaW5lU2VydmljZSk7XG4gIHByb3RlY3RlZCBfQVBJID0gaW5qZWN0KElERUFBV1NBUElTZXJ2aWNlKTtcblxuICAvKipcbiAgICogVHJ1ZSB3aGVuIHJ1bm5pbmcgYSBzeW5jaHJvbml6YXRpb24uXG4gICAqL1xuICBzeW5jaHJvbml6aW5nOiBib29sZWFuO1xuICAvKipcbiAgICogVGhlIHRpbWVzdGFtcCBvZiB0aGUgbGFzdCBzeW5jaHJvbml6YXRpb24uXG4gICAqL1xuICBsYXN0U3luY0F0OiBlcG9jaERhdGVUaW1lO1xuICAvKipcbiAgICogVHJ1ZSBpZiBhbiBlcnJvciBoYXBwZW5lZCBpbiB0aGUgbGFzdCBzeW5jaHJvbml6YXRpb24uXG4gICAqL1xuICBlcnJvckluTGFzdFN5bmM6IGJvb2xlYW47XG4gIC8qKlxuICAgKiBUcnVlIGlmIHRoZSBzeW5jaHJvbmlzYXRpb24gaXMgdG9vIHZhc3QgYW5kIHNvIHJlcXVpcmUgYSBtYW51YWwgYWN0aW9uIG9mIHRoZSB1c2VyLlxuICAgKi9cbiAgcmVxdWlyZXNNYW51YWxDb25maXJtYXRpb246IGJvb2xlYW47XG4gIC8qKlxuICAgKiBJZiBmYWxzZSwgaWdub3JlIHRoZSBlbnRpcmUgdXBsb2FkIHNjZW5hcmlvLlxuICAgKi9cbiAgdXNlUXVldWVBUElSZXF1ZXN0czogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRoZSBhcnJheSBvZiB0aGUgcmVxdWVzdHMgbm90IGV4ZWN1dGVkIGJlY2F1c2Ugd2UgYXJlL3dlcmUgb2ZmbGluZTsgdGhleSBuZWVkIHRvIHJ1biBvbmNlIG9ubGluZS5cbiAgICovXG4gIHF1ZXVlQVBJUmVxdWVzdHM6IEFQSVJlcXVlc3RbXTtcblxuICAvKipcbiAgICogVGhlIGlkIG9mIHRoZSB0ZWFtIG9mIHdoaWNoIHRvIG1hbmFnZSBkYXRhIG9mZmxpbmUuXG4gICAqIElmIG51bGwsIHRoZSBwcm9qZWN0IGlzbid0IHRlYW1zLWJhc2VkLlxuICAgKi9cbiAgcHJvdGVjdGVkIHRlYW1JZDogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGFycmF5IG9mIERlbHRhUmVzb3VyY2VzIHRvIGNhY2hlIG9mZmxpbmUuXG4gICAqL1xuICBwcm90ZWN0ZWQgcmVzb3VyY2VzOiAoRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpW107XG4gIC8qKlxuICAgKiBIZWxwZXIgc3RydWN0dXJlIHRvIG1hbmFnZSB0aGUgQ2FjaGVhYmxlUmVzb3VyY2UgZm9yIGVhY2ggRGVsdGFSZXNvdXJjZS5cbiAgICovXG4gIHByb3RlY3RlZCBjYWNoZWFibGVSZXNvdXJjZXM6IHsgW3Jlc291cmNlOiBzdHJpbmddOiBDYWNoZWFibGVSZXNvdXJjZSB9O1xuICAvKipcbiAgICogS2V5IHRvIGFjcXVpcmUgZnJvbSB0aGUgc3RvcmFnZSB0aGUgbGFzdFN5bmNBdCBpbmZvcm1hdGlvbiBvZiB0aGUgdGVhbS5cbiAgICovXG4gIHByb3RlY3RlZCBsYXN0U3luY0tleTogc3RyaW5nO1xuICAvKipcbiAgICogS2V5IHRvIGFjcXVpcmUgZnJvbSB0aGUgc3RvcmFnZSB0aGUgbGFzdFN5bmNBdCBpbmZvcm1hdGlvbiBvZiB0aGUgdGVhbS5cbiAgICovXG4gIHByb3RlY3RlZCBxdWV1ZUFQSVJlcXVlc3RLZXk6IHN0cmluZztcblxuICBjb25zdHJ1Y3RvcigpIHtcbiAgICB0aGlzLnF1ZXVlQVBJUmVxdWVzdHMgPSBuZXcgQXJyYXk8QVBJUmVxdWVzdD4oKTtcbiAgICB0aGlzLnJlc291cmNlcyA9IG5ldyBBcnJheTxzdHJpbmc+KCk7XG4gICAgdGhpcy5jYWNoZWFibGVSZXNvdXJjZXMgPSB7fTtcbiAgICAvLyBzdWJzY3JpYmUgdG8gbmV0d29yayBjaGFuZ2VzXG4gICAgdGhpcy5fb2ZmbGluZS5zdWJzY3JpYmUoaXNPbmxpbmUgPT4ge1xuICAgICAgaWYgKGlzT25saW5lKSB7XG4gICAgICAgIC8vIHRyeSBhIHN5bmNocm9uaXphdGlvbiBpZiBuZWVkZWQgb3IgaWYgdGhlIGxhc3Qgb25lIGZhaWxlZFxuICAgICAgICBpZiAodGhpcy5lcnJvckluTGFzdFN5bmMpIHRoaXMuc3luY2hyb25pemUoKTtcbiAgICAgICAgZWxzZSB0aGlzLnN5bmNocm9uaXplSWZOZWVkZWQoKTtcbiAgICAgIH1cbiAgICB9KTtcbiAgfVxuXG4gIC8vXG4gIC8vIE5FVFdPUksgU1RBVFVTIGZyb20gSURFQU9mZmxpbmVTZXJ2aWNlXG4gIC8vXG5cbiAgLyoqXG4gICAqIFF1aWNrbHkgY2hlY2sgdGhlIGNvbm5lY3Rpb24gc3RhdHVzLlxuICAgKi9cbiAgaXNPbmxpbmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX29mZmxpbmUuaXNPbmxpbmUoKTtcbiAgfVxuICAvKipcbiAgICogUXVpY2tseSBjaGVjayB0aGUgY29ubmVjdGlvbiBzdGF0dXMuXG4gICAqL1xuICBpc09mZmxpbmUoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuIHRoaXMuX29mZmxpbmUuaXNPZmZsaW5lKCk7XG4gIH1cbiAgLyoqXG4gICAqIFN1YnNjcmliZSB0byB0aGUgc2VydmljZSB0byBiZSBub3RpZmllZCB3aGVuIHRoZSBjb25uZWN0aW9uIHN0YXR1cyBjaGFuZ2VzLlxuICAgKi9cbiAgc3Vic2NyaWJlKGNhbGxiYWNrOiAoaXNPbmxpbmU6IGJvb2xlYW4pID0+IHZvaWQpOiBTdWJzY3JpcHRpb24ge1xuICAgIHJldHVybiB0aGlzLl9vZmZsaW5lLnN1YnNjcmliZShjYWxsYmFjayk7XG4gIH1cbiAgLyoqXG4gICAqIFF1aWNrbHkgY2hlY2sgZm9yIG9ubGluZSBjb25uZWN0aW9uLlxuICAgKi9cbiAgcHVibGljIGNoZWNrKCk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIHJldHVybiB0aGlzLl9vZmZsaW5lLmNoZWNrKCk7XG4gIH1cblxuICAvL1xuICAvLyBDT05GSUdVUkFUSU9OXG4gIC8vXG5cbiAgLyoqXG4gICAqIFdoZXRoZXIgdGhlIG9mZmxpbmUgbW9kZSBpcyBhbGxvd2VkLiBZb3UgY2FuIGN1c3RvbWl6ZSB0aGlzIGZ1bmN0aW9uLCBpZiBuZWVkZWQuXG4gICAqL1xuICBpc0FsbG93ZWQoKTogYm9vbGVhbiB7XG4gICAgcmV0dXJuICEhdGhpcy5yZXNvdXJjZXMubGVuZ3RoO1xuICB9XG4gIC8qKlxuICAgKiBTZXQgdXAgdGhlIHNlcnZpY2UgdG8gdXNlIGFuZCBzeW5jIG9mZmxpbmUgZGF0YS5cbiAgICovXG4gIHNldFVwT2ZmbGluZURhdGEodGVhbUlkOiBzdHJpbmcsIHVzZVF1ZXVlQVBJUmVxdWVzdHM6IGJvb2xlYW4sIGNhY2hlYWJsZVJlc291cmNlczogQ2FjaGVhYmxlUmVzb3VyY2VbXSk6IHZvaWQge1xuICAgIC8vIHNldCB0aGUgdGVhbVxuICAgIHRoaXMudGVhbUlkID0gdGVhbUlkO1xuICAgIC8vIGRlY2lkZSBpZiB0byBhbGxvdyBjZXJ0YWluIEFQSSByZXF1ZXN0IHdoaWxlIG9mZmxpbmVcbiAgICB0aGlzLnVzZVF1ZXVlQVBJUmVxdWVzdHMgPSB1c2VRdWV1ZUFQSVJlcXVlc3RzO1xuICAgIC8vIGxvYWQgdGhlIEFQSSByZXF1ZXN0IHBlbmRpbmcgcXVldWUsIGlmIGFueVxuICAgIHRoaXMucXVldWVBUElSZXF1ZXN0S2V5ID0gdGhpcy50ZWFtSWQgPyBgJHtRVUVVRV9BUElfUkVRVUVTVFNfS0VZfV8ke3RoaXMudGVhbUlkfWAgOiBRVUVVRV9BUElfUkVRVUVTVFNfS0VZO1xuICAgIHRoaXMubG9hZFF1ZXVlQVBJUmVxdWVzdCgpO1xuICAgIC8vIGxvYWQgdGhlIGxhc3RTeW5jQXQgaW5mb3JtYXRpb24gZm9yIHRoZSB0ZWFtXG4gICAgdGhpcy5sYXN0U3luY0tleSA9IHRoaXMudGVhbUlkID8gYCR7TEFTVF9TWU5DX0tFWX1fJHt0aGlzLnRlYW1JZH1gIDogTEFTVF9TWU5DX0tFWTtcbiAgICB0aGlzLmxvYWRMYXN0U3luY0F0KCk7XG4gICAgLy8gbG9hZCB0aGUgY2FjaGVhYmxlIHJlc291cmNlc1xuICAgIHRoaXMucmVzb3VyY2VzID0gbmV3IEFycmF5PERlbHRhUmVzb3VyY2VzIHwgc3RyaW5nPigpO1xuICAgIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzID0ge307XG4gICAgY2FjaGVhYmxlUmVzb3VyY2VzLmZvckVhY2gociA9PiB0aGlzLmFkZENhY2hlYWJsZVJlc291cmNlKHIpKTtcbiAgfVxuICAvKipcbiAgICogTG9hZCBmcm9tIHRoZSBsb2NhbCBzdG9yYWdlIHRoZSBsYXN0IHN5bmMgYXQgaW5mb3JtYXRpb24uXG4gICAqL1xuICBwcm90ZWN0ZWQgbG9hZExhc3RTeW5jQXQoKTogUHJvbWlzZTxudW1iZXI+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICB0aGlzLl9zdG9yYWdlLmdldCh0aGlzLmxhc3RTeW5jS2V5KS50aGVuKChsYXN0U3luY0F0OiBudW1iZXIpOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5sYXN0U3luY0F0ID0gbGFzdFN5bmNBdCA/IE51bWJlcihsYXN0U3luY0F0KSA6IG51bGw7XG4gICAgICAgIHJlc29sdmUodGhpcy5sYXN0U3luY0F0KTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBVcGRhdGUgbGFzdCBzeW5jIGF0IGluZm8gaW4gdGhlIGxvY2FsIHN0b3JhZ2UuXG4gICAqL1xuICBwcm90ZWN0ZWQgc2F2ZUxhc3RTeW5jQXQobGFzdFN5bmNBdDogbnVtYmVyKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgdGhpcy5sYXN0U3luY0F0ID0gbGFzdFN5bmNBdDtcbiAgICByZXR1cm4gdGhpcy5fc3RvcmFnZS5zZXQodGhpcy5sYXN0U3luY0tleSwgbGFzdFN5bmNBdCk7XG4gIH1cbiAgLyoqXG4gICAqIEFkZCBhIENhY2hlYWJsZVJlc291cmNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFkZENhY2hlYWJsZVJlc291cmNlKGNhY2hlYWJsZVJlc291cmNlOiBDYWNoZWFibGVSZXNvdXJjZSk6IHZvaWQge1xuICAgIGlmICh0aGlzLnRlYW1JZCkgY2FjaGVhYmxlUmVzb3VyY2UudGVhbUlkID0gdGhpcy50ZWFtSWQ7XG4gICAgdGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbY2FjaGVhYmxlUmVzb3VyY2UucmVzb3VyY2VdID0gY2FjaGVhYmxlUmVzb3VyY2U7XG4gICAgdGhpcy5yZXNvdXJjZXMucHVzaChjYWNoZWFibGVSZXNvdXJjZS5yZXNvdXJjZSk7XG4gIH1cbiAgLyoqXG4gICAqIFJlbW92ZSBhIENhY2hlYWJsZVJlc291cmNlIGJ5IGl0cyBEZWx0YVJlc291cmNlLlxuICAgKi9cbiAgcHJvdGVjdGVkIHJlbW92ZUNhY2hlYWJsZVJlc291cmNlKHJlc291cmNlOiBEZWx0YVJlc291cmNlcyB8IHN0cmluZyk6IHZvaWQge1xuICAgIGRlbGV0ZSB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV07XG4gICAgdGhpcy5yZXNvdXJjZXMuc3BsaWNlKHRoaXMucmVzb3VyY2VzLmluZGV4T2YocmVzb3VyY2UpLCAxKTtcbiAgfVxuICAvKipcbiAgICogR2V0IHRoZSB0aGUgRGVsdGFSZXNvdXJjZWQgY29uZmlndXJlZC5cbiAgICovXG4gIGdldFJlc291cmNlcygpOiAoRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpW10ge1xuICAgIHJldHVybiB0aGlzLnJlc291cmNlcztcbiAgfVxuICAvKipcbiAgICogR2V0IGEgQ2FjaGVhYmxlUmVzb3VyY2UgYnkgaXRzIERlbHRhUmVzb3VyY2UuXG4gICAqL1xuICBnZXRDYWNoZWFibGVSZXNvdXJjZShyZXNvdXJjZTogRGVsdGFSZXNvdXJjZXMgfCBzdHJpbmcpOiBDYWNoZWFibGVSZXNvdXJjZSB7XG4gICAgcmV0dXJuIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXTtcbiAgfVxuXG4gIC8vXG4gIC8vIFVQTE9BRFxuICAvL1xuXG4gIC8qKlxuICAgKiBFeGVjdXRlIGFsbCB0aGUgQVBJIHJlcXVlc3RzIGluIHRoZSBxdWV1ZTsgdGhlIHJlcXVlc3RzIHRlcm1pbmF0ZWQgd2l0aCBhbiBlcnJvciB3aWxsIHJlbWFpbiBpbiB0aGUgcXVldWUuXG4gICAqL1xuICBwcm90ZWN0ZWQgcnVuUXVldWVBUElSZXF1ZXN0cygpOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKCF0aGlzLnVzZVF1ZXVlQVBJUmVxdWVzdHMgfHwgdGhpcy5pc09mZmxpbmUoKSB8fCAhdGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmxlbmd0aCkgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgIHRoaXMucXVldWVBUElSZXF1ZXN0cy5mb3JFYWNoKGFzeW5jIHJlcXVlc3QgPT4ge1xuICAgICAgICBjb25zdCBvcHRpb25zOiBBUElSZXF1ZXN0T3B0aW9uID0ge307XG4gICAgICAgIGlmIChyZXF1ZXN0LnJlc291cmNlSWQpIG9wdGlvbnMucmVzb3VyY2VJZCA9IHJlcXVlc3QucmVzb3VyY2VJZDtcbiAgICAgICAgaWYgKHJlcXVlc3QuYm9keSkgb3B0aW9ucy5ib2R5ID0gcmVxdWVzdC5ib2R5O1xuICAgICAgICBsZXQgcHJvbWlzZTogUHJvbWlzZTxhbnk+O1xuICAgICAgICB0cnkge1xuICAgICAgICAgIHN3aXRjaCAocmVxdWVzdC5tZXRob2QudG9VcHBlckNhc2UoKSkge1xuICAgICAgICAgICAgY2FzZSAnUE9TVCc6XG4gICAgICAgICAgICAgIHByb21pc2UgPSBhd2FpdCB0aGlzLl9BUEkucG9zdFJlc291cmNlKHJlcXVlc3QucmVzb3VyY2UsIG9wdGlvbnMpO1xuICAgICAgICAgICAgICBicmVhaztcbiAgICAgICAgICAgIGNhc2UgJ1BVVCc6XG4gICAgICAgICAgICAgIHByb21pc2UgPSBhd2FpdCB0aGlzLl9BUEkucHV0UmVzb3VyY2UocmVxdWVzdC5yZXNvdXJjZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgICAgY2FzZSAnUEFUQ0gnOlxuICAgICAgICAgICAgICBwcm9taXNlID0gYXdhaXQgdGhpcy5fQVBJLnBhdGNoUmVzb3VyY2UocmVxdWVzdC5yZXNvdXJjZSwgb3B0aW9ucyk7XG4gICAgICAgICAgICAgIGJyZWFrO1xuICAgICAgICAgIH1cbiAgICAgICAgICBpZiAoIXByb21pc2UpIHJlcXVlc3QuZXJyb3IgPSAnSU5WQUxJRF9NRVRIT0QnO1xuICAgICAgICAgIGVsc2UgcmVxdWVzdC5lcnJvciA9IG51bGw7XG4gICAgICAgIH0gY2F0Y2ggKGVycikge1xuICAgICAgICAgIHJlcXVlc3QuZXJyb3IgPSAoZXJyIGFzIEVycm9yKS5tZXNzYWdlIHx8ICdVTktOT1dOX0VSUk9SJztcbiAgICAgICAgfVxuICAgICAgfSk7XG4gICAgICAvLyBrZWVwIHRoZSByZXF1ZXN0cyBOT1Qgc3VjY2Vzc2Z1bGx5IGV4ZWN1dGVkXG4gICAgICB0aGlzLnNhdmVRdWV1ZUFQSVJlcXVlc3QodGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmZpbHRlcih4ID0+IHguZXJyb3IpKS50aGVuKCgpOiB2b2lkID0+IHtcbiAgICAgICAgLy8gaWYgdGhlIHF1ZXVlIGlzIGVtcHR5LCB0aGUgZW50aXJlIG9wZXJhdGlvbiB3YXMgc3VjY2Vzc2Z1bFxuICAgICAgICBpZiAodGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmxlbmd0aCkgcmVqZWN0KCk7XG4gICAgICAgIGVsc2UgcmVzb2x2ZSgpO1xuICAgICAgfSk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIExvYWQgZnJvbSB0aGUgbG9jYWwgc3RvcmFnZSB0aGUgQVBJIHJlcXVlc3RzIHF1ZXVlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGxvYWRRdWV1ZUFQSVJlcXVlc3QoKTogUHJvbWlzZTxBUElSZXF1ZXN0W10+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UocmVzb2x2ZSA9PiB7XG4gICAgICBpZiAoIXRoaXMudXNlUXVldWVBUElSZXF1ZXN0cykgcmV0dXJuIHJlc29sdmUoW10pO1xuICAgICAgdGhpcy5fc3RvcmFnZS5nZXQodGhpcy5xdWV1ZUFQSVJlcXVlc3RLZXkpLnRoZW4oKHF1ZXVlOiBBUElSZXF1ZXN0W10pOiB2b2lkID0+IHtcbiAgICAgICAgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzID0gcXVldWUgfHwgW107XG4gICAgICAgIHJlc29sdmUodGhpcy5xdWV1ZUFQSVJlcXVlc3RzKTtcbiAgICAgIH0pO1xuICAgIH0pO1xuICB9XG4gIC8qKlxuICAgKiBVcGRhdGUgdGhlIHF1ZXVlIGluIG1lbW9yeSBhbmQgYWxzbyBzYXZlIHRoZSBjb3B5IGluIHRoZSBsb2NhbCBzdG9yYWdlLlxuICAgKi9cbiAgc2F2ZVF1ZXVlQVBJUmVxdWVzdChxdWV1ZT86IEFQSVJlcXVlc3RbXSk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSkgcmV0dXJuIFByb21pc2UucmVqZWN0KCk7XG4gICAgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzID0gcXVldWUgfHwgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzO1xuICAgIHJldHVybiB0aGlzLl9zdG9yYWdlLnNldCh0aGlzLnF1ZXVlQVBJUmVxdWVzdEtleSwgdGhpcy5xdWV1ZUFQSVJlcXVlc3RzKTtcbiAgfVxuICAvKipcbiAgICogRGVsZXRlIGEgcmVxdWVzdCBzdHVjayBpbiBhbiBlcnJvci5cbiAgICovXG4gIGRlbGV0ZVJlcXVlc3QocmVxdWVzdDogQVBJUmVxdWVzdCkge1xuICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSkgcmV0dXJuIFByb21pc2UucmVqZWN0KCk7XG4gICAgaWYgKHJlcXVlc3QpIHtcbiAgICAgIHRoaXMucXVldWVBUElSZXF1ZXN0cy5zcGxpY2UodGhpcy5xdWV1ZUFQSVJlcXVlc3RzLmluZGV4T2YocmVxdWVzdCksIDEpO1xuICAgICAgdGhpcy5zYXZlUXVldWVBUElSZXF1ZXN0KCk7XG4gICAgfVxuICB9XG5cbiAgLy9cbiAgLy8gRE9XTkxPQURcbiAgLy9cblxuICAvKipcbiAgICogU2F2ZSB0aGUgcmVjb3JkcyBvZiBhIGRlbHRhIGFuZCwgaWYgdGhlIGxhdHRlciBoYXMgbW9yZSBwYWdlcywgZ28gcmVjdXJzaXZlLlxuICAgKi9cbiAgcHJvdGVjdGVkIGFzeW5jIHN5bmNEZWx0YVJlY29yZHMoZGVsdGE6IERlbHRhLCBkb25lPzogYW55KTogUHJvbWlzZTxhbnk+IHtcbiAgICAvLyBmb3IgZWFjaCByZXNvdXJjZSwgd2UgcmVzZXQgdGhlIHN0YXR1czsgaWYgYSByZXNvdXJjZSBzdGlsbCBuZWVkIHRvIGJlIHN5bmNocm9uaXplZCwgaXQgd2lsbCBiZSBmbGFnZ2VkIGJlbG93XG4gICAgdGhpcy5yZXNvdXJjZXMuZm9yRWFjaChyZXNvdXJjZSA9PiB7XG4gICAgICB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV0uZXJyb3IgPSBmYWxzZTtcbiAgICAgIHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXS5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgfSk7XG4gICAgdHJ5IHtcbiAgICAgIC8vIHN5bmNocm9uemUgZWFjaCBvZiB0aGUgcmVzb3VyY2VzIGluY2x1ZGVkIGluIHRoZSBkZWx0YTsgdGhpcyBleGVjdXRpb24gY2FuIGdvIGluIHBhcmFsbGVsXG4gICAgICBhd2FpdCBQcm9taXNlLmFsbChcbiAgICAgICAgZGVsdGEucmVzb3VyY2VzLm1hcChhc3luYyByZXNvdXJjZSA9PiB7XG4gICAgICAgICAgY29uc3QgY3IgPSB0aGlzLmNhY2hlYWJsZVJlc291cmNlc1tyZXNvdXJjZV07XG4gICAgICAgICAgaWYgKGNyKSB7XG4gICAgICAgICAgICAvLyBzeW5jaHJvbml6ZSB0aGUgZGVsdGEgcmVjb3Jkczsgbm90ZTogdGhlIGV4ZWN1dHVpb24gaW5zaWRlIGEgcmVzb3VyY2UgbXVzdCBnbyBpbiBzZXJpZXNcbiAgICAgICAgICAgIGNyLnN5bmNocm9uaXppbmcgPSB0cnVlO1xuICAgICAgICAgICAgY29uc3Qgc3VjY2VzcyA9IGF3YWl0IHRoaXMuc3luY1Jlc291cmNlRGVsdGFSZWNvcmRzKHJlc291cmNlLCBkZWx0YS5yZWNvcmRzW3Jlc291cmNlXSk7XG4gICAgICAgICAgICBpZiAoIXN1Y2Nlc3MpIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICB9XG4gICAgICAgIH0pXG4gICAgICApO1xuICAgICAgLy8gaWYgdGhlcmUgd2VyZSBlcnJvciBvZiBpZiB0aGVyZSBpcyBub3RoaW5nIGxlZnQgdG8gc3luYywgd2UgYXJlIGRvbmVcbiAgICAgIGlmICh0aGlzLmVycm9ySW5MYXN0U3luYyB8fCAhZGVsdGEubmV4dCkgcmV0dXJuIGRvbmUoKTtcbiAgICAgIC8vIG90aGVyd2lzZSwgZ2V0IHRoZSBuZXh0IHBhZ2Ugb2YgdGhlIGRlbHRhIGFuZCBnbyByZWN1cnNpdmUgdW50aWwgd2UgYXJlIGRvbmVcbiAgICAgIGNvbnN0IHBhcmFtczogYW55ID0geyBuZXh0OiBkZWx0YS5uZXh0LCBsaW1pdDogTlVNX0VMRU1FTlRTX1dJVEhfTUFOVUFMX1NZTkMgfTtcbiAgICAgIGlmICh0aGlzLmxhc3RTeW5jQXQpIHBhcmFtcy5zaW5jZSA9IHRoaXMubGFzdFN5bmNBdDtcbiAgICAgIGNvbnN0IG5ld0RlbHRhID0gYXdhaXQgdGhpcy5fQVBJLmdldFJlc291cmNlKHRoaXMudGVhbUlkID8gYHRlYW1zLyR7dGhpcy50ZWFtSWR9L2RlbHRhYCA6ICdkZWx0YScsIHsgcGFyYW1zIH0pO1xuICAgICAgdGhpcy5zeW5jRGVsdGFSZWNvcmRzKG5ld0RlbHRhLCBkb25lKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGlmIHNvbWV0aGluZyB3ZW50IHdyb25nLCBzdG9wcyB0aGUgb3BlcmF0aW9uLCBzaW5jZSB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgZW50aXJlIGZsb3cgaXMgY29uc2lzdGVudFxuICAgICAgdGhpcy5lcnJvckluTGFzdFN5bmMgPSB0cnVlO1xuICAgICAgcmV0dXJuIGRvbmUoKTtcbiAgICB9XG4gIH1cbiAgLyoqXG4gICAqIFNhdmUgb2ZmbGluZSBhIGxpc3Qgb2YgRGVsdGFSZWNvcmRzIGZvciB0aGlzIHJlc291cmNlLCBjcmVhdGluZyBhIG1hcCBvZiBhbGwgdGhlIGNvcnJlc3BvbmRpbmcgQVBJIEdFVCByZXF1ZXN0cy5cbiAgICovXG4gIHByb3RlY3RlZCBhc3luYyBzeW5jUmVzb3VyY2VEZWx0YVJlY29yZHMocmVzb3VyY2U6IHN0cmluZywgcmVjb3JkczogRGVsdGFSZWNvcmRbXSk6IFByb21pc2U8Ym9vbGVhbj4ge1xuICAgIC8vIGFjcXVpcmUgdGhlIGluZm8gYW4gYSBjYWNoZWFibGUgcmVzb3VyY2VcbiAgICBjb25zdCBjciA9IHRoaXMuY2FjaGVhYmxlUmVzb3VyY2VzW3Jlc291cmNlXTtcbiAgICBpZiAoIWNyKSByZXR1cm4gUHJvbWlzZS5yZXNvbHZlKHRydWUpO1xuICAgIHRyeSB7XG4gICAgICAvLyBwcmVwYXJlIGhlbHBlcnMgdG8gZ3JvdXAgZXhlY3V0aW9ucyBvZiBlbGVtZW50cyBvZiB0aGUgc2FtZSBsaXN0XG4gICAgICBsZXQgbGlzdDogYW55W10gPSBudWxsLFxuICAgICAgICBvbGRMaXN0VVJMOiBzdHJpbmcgPSBudWxsO1xuICAgICAgZm9yIChjb25zdCByIG9mIHJlY29yZHMpIHtcbiAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBVUkwgdG8gYWNjZXNzIHRoZSBBUEkgcmVxdWVzdCBrZXkgZm9yIHRoaXMgZWxlbWVudFxuICAgICAgICBjb25zdCBlbGVtZW50VVJMID0gY3IuZWxlbWVudFVSTChyLmVsZW1lbnQpO1xuICAgICAgICAvLyBpZiB0aGUgZWxlbWVudCB3YXMgZGVsZXRlZCAoYmFzZWQgb24gZGVsdGEpLCBkZWxldGUgaXRzIGNvcnJlc3BvbmRpbmcgQVBJIEdFVCByZXF1ZXN0XG4gICAgICAgIGlmIChyLmRlbGV0ZWQpIGF3YWl0IHRoaXMuX0FQSS5kZWxldGVGcm9tQ2FjaGUoZWxlbWVudFVSTCk7XG4gICAgICAgIC8vIG90aGVyd2lzZSwgdXBkYXRlIGl0XG4gICAgICAgIGVsc2UgYXdhaXQgdGhpcy5fQVBJLnB1dEluQ2FjaGUoZWxlbWVudFVSTCwgci5lbGVtZW50KTtcbiAgICAgICAgLy8gY2FsY3VsYXRlIHRoZSBVUkxzIHRvIGFjY2VzcyB0aGUgQVBJIHJlcXVlc3Qga2V5IGZvciB0aGlzIGVsZW1lbnQncyBsaXN0XG4gICAgICAgIGNvbnN0IGxpc3RVUkwgPSBjci5saXN0VVJMKHIuZWxlbWVudCk7XG4gICAgICAgIC8vIHRvIGltcHJvdmUgdGhlIHBlcmZvcm1hbmNlLCBnZXQvc29ydC9zYXZlIHRoZSBsaXN0IG9ubHkgd2hlbiBpdCBjaGFuZ2VzIGZyb20gdGhlIHByZXZpb3VzIGVsZW1lbnQncyBvbmUuXG4gICAgICAgIGlmIChsaXN0VVJMICE9PSBvbGRMaXN0VVJMKSB7XG4gICAgICAgICAgLy8gc2tpcCBmaXJzdCBjeWNsZSAob2xkTGlzdFVSTCA9PT0gbnVsbClcbiAgICAgICAgICBpZiAob2xkTGlzdFVSTCkge1xuICAgICAgICAgICAgLy8gcmUtc29ydCB0aGUgbGlzdDsgbm90ZTogaXQgc2hvdWxkIGJlIHNvcnRlZCBmcm9tIHRoZSBsYXN0IHRpbWUsIHNvIHdlIG9ubHkgbWFuYWdlIHRoZSBuZXcgZWxlbWVudFxuICAgICAgICAgICAgbGlzdCA9IGxpc3Quc29ydChjci5zb3J0KTtcbiAgICAgICAgICAgIC8vIHNhdmUgdGhlIHVwZGF0ZWQgbGlzdFxuICAgICAgICAgICAgYXdhaXQgdGhpcy5fQVBJLnB1dEluQ2FjaGUob2xkTGlzdFVSTCwgbGlzdCk7XG4gICAgICAgICAgfVxuICAgICAgICAgIC8vIGdldCB0aGUgbGlzdCBvZiBlbGVtZW50cyBmcm9tIHRoZSBsb2NhbCBzdG9yYWdlIGJ5IHRoZSBjYWxjdWxhdGVkIFVSTFxuICAgICAgICAgIGxpc3QgPSBhd2FpdCB0aGlzLl9BUEkuZ2V0RnJvbUNhY2hlKGxpc3RVUkwpO1xuICAgICAgICAgIC8vIHNhdmUgdGhlIHJlZmVyZW5jZSB0byB0aGUgbGlzdCBmb3IgdGhlIG5leHQgY3ljbGVcbiAgICAgICAgICBvbGRMaXN0VVJMID0gbGlzdFVSTDtcbiAgICAgICAgfVxuICAgICAgICAvLyBmaW5kIGluIHRoZSBsaXN0IHRoZSBlbGVtZW50IHdlIHdhbnQgdG8gbWFuYWdlXG4gICAgICAgIGNvbnN0IGluZGV4ID0gY3IuZmluZEluZGV4SW5MaXN0KGxpc3QsIHIuZWxlbWVudCk7XG4gICAgICAgIC8vIGRlbGV0ZSB0aGUgZWxlbWVudCBmcm9tIHRoZSBsaXN0XG4gICAgICAgIGlmIChpbmRleCAhPT0gLTEpIGxpc3Quc3BsaWNlKGluZGV4LCAxKTtcbiAgICAgICAgLy8gaWYgdGhlIGVsZW1lbnQgd2Fzbid0IGRlbGV0ZWQgKGZvbGxvd2luZyB0aGUgZGVsdGEgcmVjb3JkIGluZm9ybWF0aW9uKSwgaW5zZXJ0IHRoZSBuZXcgdmVyc2lvblxuICAgICAgICBpZiAoIXIuZGVsZXRlZCkgbGlzdC5wdXNoKHIuZWxlbWVudCk7XG4gICAgICB9XG4gICAgICAvLyBpbiBjYXNlIHRoZXJlIHdlcmUgZWxlbWVudHMsIHNhdmUgdGhlIGxhc3QgZWxlbWVudCdzIGxpc3RcbiAgICAgIGlmIChvbGRMaXN0VVJMKSB7XG4gICAgICAgIC8vIHJlLXNvcnQgdGhlIGxpc3Q7IG5vdGU6IGl0IHNob3VsZCBiZSBzb3J0ZWQgZnJvbSB0aGUgbGFzdCB0aW1lLCBzbyB3ZSBvbmx5IG1hbmFnZSB0aGUgbmV3IGVsZW1lbnRcbiAgICAgICAgbGlzdCA9IGxpc3Quc29ydChjci5zb3J0KTtcbiAgICAgICAgLy8gc2F2ZSB0aGUgdXBkYXRlZCBsaXN0XG4gICAgICAgIGF3YWl0IHRoaXMuX0FQSS5wdXRJbkNhY2hlKG9sZExpc3RVUkwsIGxpc3QpO1xuICAgICAgfVxuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZSh0cnVlKTtcbiAgICB9IGNhdGNoIChlcnIpIHtcbiAgICAgIC8vIGlmIHNvbWV0aGluZyB3ZW50IHdyb25nLCBzdG9wcyB0aGUgb3BlcmF0aW9uLCBzaW5jZSB3ZSBuZWVkIHRvIG1ha2Ugc3VyZSB0aGUgZW50aXJlIGZsb3cgaXMgY29uc2lzdGVudFxuICAgICAgY3IuZXJyb3IgPSB0cnVlO1xuICAgICAgcmV0dXJuIFByb21pc2UucmVzb2x2ZShmYWxzZSk7XG4gICAgfVxuICB9XG5cbiAgLy9cbiAgLy8gU1lOQ0hST05JU0FUSU9OIChVUExPQUQrRE9XTkxPQUQpXG4gIC8vXG5cbiAgLyoqXG4gICAqIFJ1biBhIHN5bmMsIGJ1dCBvbmx5IGlmIG5lZWRlZCwgaS5lLiB0aGUgY2FjaGVkIGNvbnRlbnQgZXhwaXJlZCBvciB3ZSBoYXZlIHBlbmRpbmcgQVBJIHJlcXVlc3RzIGluIHRoZSBxdWV1ZS5cbiAgICovXG4gIHN5bmNocm9uaXplSWZOZWVkZWQoKTogUHJvbWlzZTx2b2lkPiB7XG4gICAgcmV0dXJuIG5ldyBQcm9taXNlKChyZXNvbHZlLCByZWplY3QpOiB2b2lkID0+IHtcbiAgICAgIGlmICghdGhpcy5pc0FsbG93ZWQoKSkgcmV0dXJuO1xuICAgICAgdGhpcy5sb2FkTGFzdFN5bmNBdCgpLnRoZW4oXG4gICAgICAgICgpOiBQcm9taXNlPHZvaWQ+ID0+XG4gICAgICAgICAgdGhpcy5sb2FkUXVldWVBUElSZXF1ZXN0KClcbiAgICAgICAgICAgIC50aGVuKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgaWYgKHRoaXMucXVldWVBUElSZXF1ZXN0cy5sZW5ndGggfHwgRGF0ZS5ub3coKSA+IHRoaXMubGFzdFN5bmNBdCArIFNZTkNfRVhQSVJBVElPTl9JTlRFUlZBTClcbiAgICAgICAgICAgICAgICB0aGlzLnN5bmNocm9uaXplKCk7XG4gICAgICAgICAgICAgIHJlc29sdmUoKTtcbiAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAuY2F0Y2goZXJyID0+IHJlamVjdChlcnIpKVxuICAgICAgKTtcbiAgICB9KTtcbiAgfVxuICAvKipcbiAgICogU3luY2hyb25pemF0aW9uIG9mIHRoZSB3aG9sZSBzZXQgb2YgcmVzb3VyY2VzICh1cGxvYWQrZG93bmxvYWQpLlxuICAgKiBAcGFyYW0gbWFudWFsQ29uZmlybWF0aW9uIGlmIHRydWUsIHRoZSByZXF1ZXN0IGNvbWVzIGRpcmVjdGx5IGZyb20gYSB1c2VyIGFjdGlvbiAobm90IGF1dG9tYXRpYyBwcm9jZWR1cmVzKS5cbiAgICovXG4gIHN5bmNocm9uaXplKG1hbnVhbENvbmZpcm1hdGlvbj86IGJvb2xlYW4pOiBQcm9taXNlPHZvaWQ+IHtcbiAgICByZXR1cm4gbmV3IFByb21pc2UoKHJlc29sdmUsIHJlamVjdCk6IHZvaWQgPT4ge1xuICAgICAgaWYgKCF0aGlzLmlzQWxsb3dlZCgpIHx8IHRoaXMuc3luY2hyb25pemluZykgcmV0dXJuIHJlc29sdmUoKTtcbiAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IHRydWU7XG4gICAgICB0aGlzLmVycm9ySW5MYXN0U3luYyA9IGZhbHNlO1xuICAgICAgdGhpcy5yZXF1aXJlc01hbnVhbENvbmZpcm1hdGlvbiA9IGZhbHNlO1xuICAgICAgLy8gbG9hZCB0aGUgbGFzdFN5bmNBdCBpbmZvcm1hdGlvblxuICAgICAgdGhpcy5sb2FkTGFzdFN5bmNBdCgpLnRoZW4oXG4gICAgICAgICgpOiBQcm9taXNlPHZvaWQ+ID0+XG4gICAgICAgICAgLy8gdHJ5IHRvIHJ1biBhbGwgdGhlIHBlbmRpbmcgQVBJIHJlcXVlc3RzIGluIHRoZSBxdWV1ZSwgaS5lLiB1cGxvYWRpbmcgdGhlIG9mZmxpbmUgcmVzb3VyY2VzIGNoYW5nZWRcbiAgICAgICAgICB0aGlzLnJ1blF1ZXVlQVBJUmVxdWVzdHMoKVxuICAgICAgICAgICAgLnRoZW4oKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAvLyBzZXQgdGhpcyBtb21lbnQgaW4gdGltZTogaWYgYW55dGhpbmcgaGFwcGVuZWQgYmVmb3JlIHRoZSBlbmQgb2YgdGhlIHN5bmMsIHdlIGRvbid0IGxvc2UgZnJlc2ggZGF0YVxuICAgICAgICAgICAgICBjb25zdCBub3cgPSBEYXRlLm5vdygpO1xuICAgICAgICAgICAgICAvLyBwcmVwYXJlIGEgZmlyc3QgXCJzaG9ydFwiIERlbHRhIHJlcXVlc3QsIHRvIHNlZSBpZiB0aGVyZSBpcyBhIGxvdCBvZiBkYXRhIHRvIHByb2Nlc3NcbiAgICAgICAgICAgICAgY29uc3QgcGFyYW1zOiBhbnkgPSB7IGxpbWl0OiBOVU1fRUxFTUVOVFNfV0lUSE9VVF9NQU5VQUxfU1lOQyB9O1xuICAgICAgICAgICAgICBpZiAodGhpcy5sYXN0U3luY0F0KSBwYXJhbXMuc2luY2UgPSB0aGlzLmxhc3RTeW5jQXQ7XG4gICAgICAgICAgICAgIHRoaXMuX0FQSVxuICAgICAgICAgICAgICAgIC5nZXRSZXNvdXJjZSh0aGlzLnRlYW1JZCA/IGB0ZWFtcy8ke3RoaXMudGVhbUlkfS9kZWx0YWAgOiAnZGVsdGEnLCB7IHBhcmFtcyB9KVxuICAgICAgICAgICAgICAgIC50aGVuKChkZWx0YTogRGVsdGEpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIGRlY2lkZSBpZiB0byBwcm9jZWVkIHdpdGggdGhlIHN5bmM6IGluIGNhc2UgdGhlcmUgaXMgYW5vdGhlciBwYWdlLCBpdCByZXF1aXJlcyBhIG1hbnVhbCBjb25maXJtYXRpb25cbiAgICAgICAgICAgICAgICAgIGlmIChkZWx0YS5uZXh0ICYmICFtYW51YWxDb25maXJtYXRpb24pIHtcbiAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXF1aXJlc01hbnVhbENvbmZpcm1hdGlvbiA9IHRydWU7XG4gICAgICAgICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgICByZXR1cm4gcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgfVxuICAgICAgICAgICAgICAgICAgLy8gc2F2ZSB0aGUgcmVjb3JkcyBpbiB0aGUgZGVsdGEgYW5kIHJlcXVlc3QgcG9zc2libGUgbmV3IHBhZ2VzXG4gICAgICAgICAgICAgICAgICB0aGlzLnN5bmNEZWx0YVJlY29yZHMoZGVsdGEsICgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgICAgaWYgKHRoaXMuZXJyb3JJbkxhc3RTeW5jKSB7XG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICB9IGVsc2Uge1xuICAgICAgICAgICAgICAgICAgICAgIC8vIGFsbCB0aGUgcmVzb3VyY2VzIGFyZSBzdWNjZXNmdWxseSBpbiBzeW5jXG4gICAgICAgICAgICAgICAgICAgICAgdGhpcy5yZXNvdXJjZXMuZm9yRWFjaChyZXNvdXJjZSA9PiAodGhpcy5jYWNoZWFibGVSZXNvdXJjZXNbcmVzb3VyY2VdLnN5bmNocm9uaXppbmcgPSBmYWxzZSkpO1xuICAgICAgICAgICAgICAgICAgICAgIC8vIHVwZGF0ZSB0aGUgdGltZXN0YW1wIG9mIGxhc3Qgc3luY1xuICAgICAgICAgICAgICAgICAgICAgIHRoaXMuc2F2ZUxhc3RTeW5jQXQobm93KVxuICAgICAgICAgICAgICAgICAgICAgICAgLnRoZW4oKCk6IHZvaWQgPT4ge1xuICAgICAgICAgICAgICAgICAgICAgICAgICB0aGlzLnN5bmNocm9uaXppbmcgPSBmYWxzZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgcmVzb2x2ZSgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSlcbiAgICAgICAgICAgICAgICAgICAgICAgIC5jYXRjaCgoKTogdm9pZCA9PiB7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIC8vIHdlIGNvdWxkbid0IHNhdmUgdGhlIGxhc3Qgc3luYyBpbmZvXG4gICAgICAgICAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICAgICAgICAgIH1cbiAgICAgICAgICAgICAgICAgIH0pO1xuICAgICAgICAgICAgICAgIH0pXG4gICAgICAgICAgICAgICAgLmNhdGNoKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgICAgIC8vIHdlIGNvdWxkbid0IGFjcXVpcmUgbmV3IGluZm9ybWF0aW9uIChEZWx0YSlcbiAgICAgICAgICAgICAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgICAgICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgICAgICAgICAgICAgICAgcmVqZWN0KCk7XG4gICAgICAgICAgICAgICAgfSk7XG4gICAgICAgICAgICB9KVxuICAgICAgICAgICAgLmNhdGNoKCgpOiB2b2lkID0+IHtcbiAgICAgICAgICAgICAgLy8gd2Ugc3RvcCwgc2luY2Ugd2UgZG9uJ3Qgd2FudCBiYWNrZW5kIGRhdGEgdG8gb3ZlcnJpZGUgbG9jYWwgaW5mbyBub3QgeWV0IHVwbG9hZGVkXG4gICAgICAgICAgICAgIHRoaXMuZXJyb3JJbkxhc3RTeW5jID0gdHJ1ZTtcbiAgICAgICAgICAgICAgdGhpcy5zeW5jaHJvbml6aW5nID0gZmFsc2U7XG4gICAgICAgICAgICAgIHJlamVjdCgpO1xuICAgICAgICAgICAgfSlcbiAgICAgICk7XG4gICAgfSk7XG4gIH1cbiAgLyoqXG4gICAqIEZvcmNlIGEgZnVsbCBzeW5jaHJvbmlzYXRpb24uXG4gICAqL1xuICBmb3JjZUZ1bGxTeW5jKCk6IHZvaWQge1xuICAgIHRoaXMuX3N0b3JhZ2UuY2xlYXIoKS50aGVuKCgpOiBQcm9taXNlPHZvaWQ+ID0+IHRoaXMuc3luY2hyb25pemUodHJ1ZSkpO1xuICB9XG59XG5cbi8qKlxuICogVGhlIGRlc2NyaXB0aW9uIG9mIGFuIEFQSSByZXF1ZXN0IHRvIGEgcmVzb3VyY2UsIHRvIHVzZSB3aXRoIGBJREVBQVdTQVBJYC5cbiAqIFVzZWQgZm9yIHF1ZXVlcyBvZiByZXF1ZXN0cyAoVVBMT0FEKS5cbiAqL1xuZXhwb3J0IGludGVyZmFjZSBBUElSZXF1ZXN0IHtcbiAgLyoqXG4gICAqIFJlc291cmNlIHBhdGggKGUuZy4gYHVzZXJzYCBvciBgdGVhbXMvJHt0ZWFtSWR9L3VzZXJzYCkuXG4gICAqL1xuICByZXNvdXJjZTogc3RyaW5nO1xuICAvKipcbiAgICogVGhlIGlkIHRvIGlkZW50aWZ5IGEgc3BlY2lmaWMgZWxlbWVudCBvZiB0aGUgcmVzb3VyY2UuXG4gICAqL1xuICByZXNvdXJjZUlkOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgQVBJIHJlcXVlc3QgbWV0aG9kIChlLmcuIFBPU1QsIFBVVCwgUEFUQ0gpLlxuICAgKi9cbiAgbWV0aG9kOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBUaGUgYm9keSBvZiB0aGUgcmVxdWVzdC5cbiAgICovXG4gIGJvZHk6IGFueTtcbiAgLyoqXG4gICAqIEEgZGVzY3JpcHRpb24gdG8gc2hvdyBmb3IgdGhlIHJlcXVlc3QuXG4gICAqL1xuICBkZXNjcmlwdGlvbj86IHN0cmluZztcbiAgLyoqXG4gICAqIElmIG5vdCBudWxsLCB0aGUgcmVxdWVzdCB0cmllZCB0byBydW4gYnV0IGl0IGVuY291bnRlcmVkIHRoZSBlcnJvci5cbiAgICovXG4gIGVycm9yPzogc3RyaW5nO1xufVxuXG4vKipcbiAqIFRoZSBhYnN0cmFjdCBjbGFzcyB0byBpbXBsZW1lbnQgZm9yIGVhY2ggcmVzb3VyY2UgdG8gY2FjaGUgb2ZmbGluZSBmcm9tIHRoZSBiYWNrLWVuZCAoRE9XTkxPQUQpLlxuICovXG5leHBvcnQgYWJzdHJhY3QgY2xhc3MgQ2FjaGVhYmxlUmVzb3VyY2Uge1xuICAvKipcbiAgICogVGhlIHRlYW0gb3duaW5nIHRoZSByZXNvdXJjZS5cbiAgICogSWYgbnVsbCwgdGhlIHByb2plY3QgaXNuJ3QgdGVhbXMtYmFzZWQuXG4gICAqL1xuICB0ZWFtSWQ6IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSBpZGVudGlmaWVyIG9mIHRoZSByZXNvdXJjZS5cbiAgICovXG4gIHJlc291cmNlOiBEZWx0YVJlc291cmNlcyB8IHN0cmluZztcbiAgLyoqXG4gICAqIFRoZSByZXNvdXJjZSBkZXNjcmlwdGlvbiAodHJhbnNsYXRlZCkgZm9yIHRoZSBVSS5cbiAgICovXG4gIGRlc2NyaXB0aW9uOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBSdW50aW1lIGF0dHJpYnV0ZSB0byBrbm93IGlmIHRoZSByZXNvdXJjZSBpcyBzeW5jaHJvbml6aW5nLlxuICAgKi9cbiAgc3luY2hyb25pemluZzogYm9vbGVhbjtcbiAgLyoqXG4gICAqIFRydWUgaWYgb25lIG9mIHRoZSBlbGVtZW50cyBmYWlsZWQgdGhlIGV4ZWN1dGlvbi5cbiAgICovXG4gIGVycm9yOiBib29sZWFuO1xuXG4gIGNvbnN0cnVjdG9yKHJlc291cmNlOiBzdHJpbmcsIGRlc2NyaXB0aW9uOiBzdHJpbmcpIHtcbiAgICB0aGlzLnJlc291cmNlID0gcmVzb3VyY2U7XG4gICAgdGhpcy5kZXNjcmlwdGlvbiA9IGRlc2NyaXB0aW9uO1xuICAgIHRoaXMuc3luY2hyb25pemluZyA9IGZhbHNlO1xuICAgIHRoaXMuZXJyb3IgPSBmYWxzZTtcbiAgICAvLyBsb2FkZWQgYXQgcnVudGltZVxuICAgIHRoaXMudGVhbUlkID0gbnVsbDtcbiAgfVxuXG4gIC8qKlxuICAgKiBIb3cgdG8gYnVpbGQgdGhlIHJlbGF0aXZlIFVSTCB0byB0aGUgcmVzb3VyY2UgKGxpc3QpLlxuICAgKiBFLmcuIGB0ZWFtcy8ke2VsZW1lbnQudGVhbUlkfS9jdXN0b21lcnNgIG9yIGBjdXN0b21lcnNgLlxuICAgKi9cbiAgYWJzdHJhY3QgbGlzdFVSTChlbGVtZW50OiBhbnkpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBIb3cgdG8gYnVpbGQgdGhlIHJlbGF0aXZlIFVSTCB0byB0aGUgcmVzb3VyY2UgZWxlbWVudCAoZGV0YWlsKS5cbiAgICogRS5nLiBgdGVhbXMvJHtlbGVtZW50LnRlYW1JZH0vY3VzdG9tZXJzLyR7ZWxlbWVudC5jdXN0b21lcklkfWAgb3IgYGN1c3RvbWVycy8ke2VsZW1lbnQuY3VzdG9tZXJJZH1gLlxuICAgKi9cbiAgYWJzdHJhY3QgZWxlbWVudFVSTChlbGVtZW50OiBhbnkpOiBzdHJpbmc7XG4gIC8qKlxuICAgKiBIb3cgdG8gdW5pcXVlbHkgaWRlbnRpZnkgYW4gZWxlbWVudCBpbiB0aGUgbGlzdCAoYnkgaXRzIGlkcykuXG4gICAqIEUuZy4gYHJldHVybiBsaXN0LmZpbmRJbmRleCh4ID0+IHguY3VzdG9tZXJJZCA9PT0gZWxlbWVudC5jdXN0b21lcklkKTtgXG4gICAqL1xuICBhYnN0cmFjdCBmaW5kSW5kZXhJbkxpc3QobGlzdDogYW55W10sIGVsZW1lbnQ6IGFueSk6IG51bWJlcjtcbiAgLyoqXG4gICAqIEhvdyB0byBrZWVwIHRoZSBsaXN0IHNvcnRlZC5cbiAgICogRS5nLiBgcmV0dXJuIGEubmFtZS5sb2NhbGVDb21wYXJlKGIubmFtZSk7YFxuICAgKi9cbiAgYWJzdHJhY3Qgc29ydChhOiBhbnksIGI6IGFueSk6IG51bWJlcjtcbn1cbiJdfQ==
|
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
import { Component, Input, inject } from '@angular/core';
|
|
2
|
+
import { ModalController, AlertController, Platform } from '@ionic/angular';
|
|
3
|
+
import { IDEATranslationsService } from '@idea-ionic/common';
|
|
4
|
+
import { IDEAOfflineManagerComponent } from './offlineManager.component';
|
|
5
|
+
import { IDEAOfflineDataService } from './offlineData.service';
|
|
6
|
+
import * as i0 from "@angular/core";
|
|
7
|
+
import * as i1 from "@ionic/angular";
|
|
8
|
+
export class IDEAOfflineIndicatorComponent {
|
|
9
|
+
constructor() {
|
|
10
|
+
this._alert = inject(AlertController);
|
|
11
|
+
this._modal = inject(ModalController);
|
|
12
|
+
this._translate = inject(IDEATranslationsService);
|
|
13
|
+
this._platform = inject(Platform);
|
|
14
|
+
this._offline = inject(IDEAOfflineDataService);
|
|
15
|
+
/**
|
|
16
|
+
* Vertical position.
|
|
17
|
+
*/
|
|
18
|
+
this.vertical = 'bottom';
|
|
19
|
+
/**
|
|
20
|
+
* Horizontal position.
|
|
21
|
+
*/
|
|
22
|
+
this.horizontal = 'start';
|
|
23
|
+
/**
|
|
24
|
+
* Whether it is positionated on an edge.
|
|
25
|
+
*/
|
|
26
|
+
this.edge = false;
|
|
27
|
+
}
|
|
28
|
+
async showStatus() {
|
|
29
|
+
if (this._offline.isOffline()) {
|
|
30
|
+
const isOnline = await this._offline.check();
|
|
31
|
+
if (!isOnline) {
|
|
32
|
+
const alert = await this._alert.create({
|
|
33
|
+
header: this._translate._('IDEA_UNCOMMON.OFFLINE.YOU_ARE_OFFLINE'),
|
|
34
|
+
message: this._translate._('IDEA_UNCOMMON.OFFLINE.FEATURES_REDUCED_CONTENTS_NOT_UP_TO_DATE'),
|
|
35
|
+
buttons: [this._translate._('COMMON.GOT_IT')]
|
|
36
|
+
});
|
|
37
|
+
alert.present();
|
|
38
|
+
}
|
|
39
|
+
}
|
|
40
|
+
else if (this._offline.isAllowed()) {
|
|
41
|
+
const modal = await this._modal.create({ component: IDEAOfflineManagerComponent });
|
|
42
|
+
modal.present();
|
|
43
|
+
}
|
|
44
|
+
}
|
|
45
|
+
static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineIndicatorComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); }
|
|
46
|
+
static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "18.1.1", type: IDEAOfflineIndicatorComponent, selector: "idea-offline-indicator", inputs: { vertical: "vertical", horizontal: "horizontal", edge: "edge" }, ngImport: i0, template: "@if (\n _platform.is('mobile') && (_offline.isOffline() || _offline.synchronizing || _offline.requiresManualConfirmation)\n) {\n <ion-fab [vertical]=\"vertical\" [horizontal]=\"horizontal\" [edge]=\"edge\">\n <ion-fab-button color=\"dark\" size=\"small\" (click)=\"showStatus()\">\n <!-- OFFLINE -->\n @if (_offline.isOffline()) {\n <ion-icon name=\"airplane\" />\n }\n <!-- SYNCHRONISING -->\n @if (_offline.isOnline() && _offline.synchronizing) {\n <ion-icon name=\"sync\" />\n }\n <!-- NEED MANAL SYNCHRONISATION -->\n @if (_offline.isOnline() && _offline.requiresManualConfirmation) {\n <ion-icon name=\"pause\" />\n }\n </ion-fab-button>\n </ion-fab>\n}\n", styles: [""], dependencies: [{ kind: "component", type: i1.IonFab, selector: "ion-fab", inputs: ["activated", "edge", "horizontal", "vertical"] }, { kind: "component", type: i1.IonFabButton, selector: "ion-fab-button", inputs: ["activated", "closeIcon", "color", "disabled", "download", "href", "mode", "rel", "routerAnimation", "routerDirection", "show", "size", "target", "translucent", "type"] }, { kind: "component", type: i1.IonIcon, selector: "ion-icon", inputs: ["color", "flipRtl", "icon", "ios", "lazy", "md", "mode", "name", "sanitize", "size", "src"] }] }); }
|
|
47
|
+
}
|
|
48
|
+
i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "18.1.1", ngImport: i0, type: IDEAOfflineIndicatorComponent, decorators: [{
|
|
49
|
+
type: Component,
|
|
50
|
+
args: [{ selector: 'idea-offline-indicator', template: "@if (\n _platform.is('mobile') && (_offline.isOffline() || _offline.synchronizing || _offline.requiresManualConfirmation)\n) {\n <ion-fab [vertical]=\"vertical\" [horizontal]=\"horizontal\" [edge]=\"edge\">\n <ion-fab-button color=\"dark\" size=\"small\" (click)=\"showStatus()\">\n <!-- OFFLINE -->\n @if (_offline.isOffline()) {\n <ion-icon name=\"airplane\" />\n }\n <!-- SYNCHRONISING -->\n @if (_offline.isOnline() && _offline.synchronizing) {\n <ion-icon name=\"sync\" />\n }\n <!-- NEED MANAL SYNCHRONISATION -->\n @if (_offline.isOnline() && _offline.requiresManualConfirmation) {\n <ion-icon name=\"pause\" />\n }\n </ion-fab-button>\n </ion-fab>\n}\n" }]
|
|
51
|
+
}], propDecorators: { vertical: [{
|
|
52
|
+
type: Input
|
|
53
|
+
}], horizontal: [{
|
|
54
|
+
type: Input
|
|
55
|
+
}], edge: [{
|
|
56
|
+
type: Input
|
|
57
|
+
}] } });
|
|
58
|
+
//# sourceMappingURL=data:application/json;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoib2ZmbGluZUluZGljYXRvci5jb21wb25lbnQuanMiLCJzb3VyY2VSb290IjoiIiwic291cmNlcyI6WyIuLi8uLi8uLi8uLi8uLi9tb2R1bGVzL3VuY29tbW9uL3NyYy9vZmZsaW5lL29mZmxpbmVJbmRpY2F0b3IuY29tcG9uZW50LnRzIiwiLi4vLi4vLi4vLi4vLi4vbW9kdWxlcy91bmNvbW1vbi9zcmMvb2ZmbGluZS9vZmZsaW5lSW5kaWNhdG9yLmNvbXBvbmVudC5odG1sIl0sIm5hbWVzIjpbXSwibWFwcGluZ3MiOiJBQUFBLE9BQU8sRUFBRSxTQUFTLEVBQUUsS0FBSyxFQUFFLE1BQU0sRUFBRSxNQUFNLGVBQWUsQ0FBQztBQUN6RCxPQUFPLEVBQUUsZUFBZSxFQUFFLGVBQWUsRUFBRSxRQUFRLEVBQUUsTUFBTSxnQkFBZ0IsQ0FBQztBQUM1RSxPQUFPLEVBQUUsdUJBQXVCLEVBQUUsTUFBTSxvQkFBb0IsQ0FBQztBQUU3RCxPQUFPLEVBQUUsMkJBQTJCLEVBQUUsTUFBTSw0QkFBNEIsQ0FBQztBQUN6RSxPQUFPLEVBQUUsc0JBQXNCLEVBQUUsTUFBTSx1QkFBdUIsQ0FBQzs7O0FBTy9ELE1BQU0sT0FBTyw2QkFBNkI7SUFMMUM7UUFNVSxXQUFNLEdBQUcsTUFBTSxDQUFDLGVBQWUsQ0FBQyxDQUFDO1FBQ2pDLFdBQU0sR0FBRyxNQUFNLENBQUMsZUFBZSxDQUFDLENBQUM7UUFDakMsZUFBVSxHQUFHLE1BQU0sQ0FBQyx1QkFBdUIsQ0FBQyxDQUFDO1FBQ3JELGNBQVMsR0FBRyxNQUFNLENBQUMsUUFBUSxDQUFDLENBQUM7UUFDN0IsYUFBUSxHQUFHLE1BQU0sQ0FBQyxzQkFBc0IsQ0FBQyxDQUFDO1FBRTFDOztXQUVHO1FBQ00sYUFBUSxHQUFHLFFBQVEsQ0FBQztRQUM3Qjs7V0FFRztRQUNNLGVBQVUsR0FBRyxPQUFPLENBQUM7UUFDOUI7O1dBRUc7UUFDTSxTQUFJLEdBQUcsS0FBSyxDQUFDO0tBa0J2QjtJQWhCQyxLQUFLLENBQUMsVUFBVTtRQUNkLElBQUksSUFBSSxDQUFDLFFBQVEsQ0FBQyxTQUFTLEVBQUUsRUFBRSxDQUFDO1lBQzlCLE1BQU0sUUFBUSxHQUFHLE1BQU0sSUFBSSxDQUFDLFFBQVEsQ0FBQyxLQUFLLEVBQUUsQ0FBQztZQUM3QyxJQUFJLENBQUMsUUFBUSxFQUFFLENBQUM7Z0JBQ2QsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQztvQkFDckMsTUFBTSxFQUFFLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLHVDQUF1QyxDQUFDO29CQUNsRSxPQUFPLEVBQUUsSUFBSSxDQUFDLFVBQVUsQ0FBQyxDQUFDLENBQUMsZ0VBQWdFLENBQUM7b0JBQzVGLE9BQU8sRUFBRSxDQUFDLElBQUksQ0FBQyxVQUFVLENBQUMsQ0FBQyxDQUFDLGVBQWUsQ0FBQyxDQUFDO2lCQUM5QyxDQUFDLENBQUM7Z0JBQ0gsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1lBQ2xCLENBQUM7UUFDSCxDQUFDO2FBQU0sSUFBSSxJQUFJLENBQUMsUUFBUSxDQUFDLFNBQVMsRUFBRSxFQUFFLENBQUM7WUFDckMsTUFBTSxLQUFLLEdBQUcsTUFBTSxJQUFJLENBQUMsTUFBTSxDQUFDLE1BQU0sQ0FBQyxFQUFFLFNBQVMsRUFBRSwyQkFBMkIsRUFBRSxDQUFDLENBQUM7WUFDbkYsS0FBSyxDQUFDLE9BQU8sRUFBRSxDQUFDO1FBQ2xCLENBQUM7SUFDSCxDQUFDOzhHQW5DVSw2QkFBNkI7a0dBQTdCLDZCQUE2Qix3SUNaMUMsaXVCQW9CQTs7MkZEUmEsNkJBQTZCO2tCQUx6QyxTQUFTOytCQUNFLHdCQUF3Qjs4QkFjekIsUUFBUTtzQkFBaEIsS0FBSztnQkFJRyxVQUFVO3NCQUFsQixLQUFLO2dCQUlHLElBQUk7c0JBQVosS0FBSyIsInNvdXJjZXNDb250ZW50IjpbImltcG9ydCB7IENvbXBvbmVudCwgSW5wdXQsIGluamVjdCB9IGZyb20gJ0Bhbmd1bGFyL2NvcmUnO1xuaW1wb3J0IHsgTW9kYWxDb250cm9sbGVyLCBBbGVydENvbnRyb2xsZXIsIFBsYXRmb3JtIH0gZnJvbSAnQGlvbmljL2FuZ3VsYXInO1xuaW1wb3J0IHsgSURFQVRyYW5zbGF0aW9uc1NlcnZpY2UgfSBmcm9tICdAaWRlYS1pb25pYy9jb21tb24nO1xuXG5pbXBvcnQgeyBJREVBT2ZmbGluZU1hbmFnZXJDb21wb25lbnQgfSBmcm9tICcuL29mZmxpbmVNYW5hZ2VyLmNvbXBvbmVudCc7XG5pbXBvcnQgeyBJREVBT2ZmbGluZURhdGFTZXJ2aWNlIH0gZnJvbSAnLi9vZmZsaW5lRGF0YS5zZXJ2aWNlJztcblxuQENvbXBvbmVudCh7XG4gIHNlbGVjdG9yOiAnaWRlYS1vZmZsaW5lLWluZGljYXRvcicsXG4gIHRlbXBsYXRlVXJsOiAnb2ZmbGluZUluZGljYXRvci5jb21wb25lbnQuaHRtbCcsXG4gIHN0eWxlVXJsczogWydvZmZsaW5lSW5kaWNhdG9yLmNvbXBvbmVudC5zY3NzJ11cbn0pXG5leHBvcnQgY2xhc3MgSURFQU9mZmxpbmVJbmRpY2F0b3JDb21wb25lbnQge1xuICBwcml2YXRlIF9hbGVydCA9IGluamVjdChBbGVydENvbnRyb2xsZXIpO1xuICBwcml2YXRlIF9tb2RhbCA9IGluamVjdChNb2RhbENvbnRyb2xsZXIpO1xuICBwcml2YXRlIF90cmFuc2xhdGUgPSBpbmplY3QoSURFQVRyYW5zbGF0aW9uc1NlcnZpY2UpO1xuICBfcGxhdGZvcm0gPSBpbmplY3QoUGxhdGZvcm0pO1xuICBfb2ZmbGluZSA9IGluamVjdChJREVBT2ZmbGluZURhdGFTZXJ2aWNlKTtcblxuICAvKipcbiAgICogVmVydGljYWwgcG9zaXRpb24uXG4gICAqL1xuICBASW5wdXQoKSB2ZXJ0aWNhbCA9ICdib3R0b20nO1xuICAvKipcbiAgICogSG9yaXpvbnRhbCBwb3NpdGlvbi5cbiAgICovXG4gIEBJbnB1dCgpIGhvcml6b250YWwgPSAnc3RhcnQnO1xuICAvKipcbiAgICogV2hldGhlciBpdCBpcyBwb3NpdGlvbmF0ZWQgb24gYW4gZWRnZS5cbiAgICovXG4gIEBJbnB1dCgpIGVkZ2UgPSBmYWxzZTtcblxuICBhc3luYyBzaG93U3RhdHVzKCk6IFByb21pc2U8dm9pZD4ge1xuICAgIGlmICh0aGlzLl9vZmZsaW5lLmlzT2ZmbGluZSgpKSB7XG4gICAgICBjb25zdCBpc09ubGluZSA9IGF3YWl0IHRoaXMuX29mZmxpbmUuY2hlY2soKTtcbiAgICAgIGlmICghaXNPbmxpbmUpIHtcbiAgICAgICAgY29uc3QgYWxlcnQgPSBhd2FpdCB0aGlzLl9hbGVydC5jcmVhdGUoe1xuICAgICAgICAgIGhlYWRlcjogdGhpcy5fdHJhbnNsYXRlLl8oJ0lERUFfVU5DT01NT04uT0ZGTElORS5ZT1VfQVJFX09GRkxJTkUnKSxcbiAgICAgICAgICBtZXNzYWdlOiB0aGlzLl90cmFuc2xhdGUuXygnSURFQV9VTkNPTU1PTi5PRkZMSU5FLkZFQVRVUkVTX1JFRFVDRURfQ09OVEVOVFNfTk9UX1VQX1RPX0RBVEUnKSxcbiAgICAgICAgICBidXR0b25zOiBbdGhpcy5fdHJhbnNsYXRlLl8oJ0NPTU1PTi5HT1RfSVQnKV1cbiAgICAgICAgfSk7XG4gICAgICAgIGFsZXJ0LnByZXNlbnQoKTtcbiAgICAgIH1cbiAgICB9IGVsc2UgaWYgKHRoaXMuX29mZmxpbmUuaXNBbGxvd2VkKCkpIHtcbiAgICAgIGNvbnN0IG1vZGFsID0gYXdhaXQgdGhpcy5fbW9kYWwuY3JlYXRlKHsgY29tcG9uZW50OiBJREVBT2ZmbGluZU1hbmFnZXJDb21wb25lbnQgfSk7XG4gICAgICBtb2RhbC5wcmVzZW50KCk7XG4gICAgfVxuICB9XG59XG4iLCJAaWYgKFxuICBfcGxhdGZvcm0uaXMoJ21vYmlsZScpICYmIChfb2ZmbGluZS5pc09mZmxpbmUoKSB8fCBfb2ZmbGluZS5zeW5jaHJvbml6aW5nIHx8IF9vZmZsaW5lLnJlcXVpcmVzTWFudWFsQ29uZmlybWF0aW9uKVxuKSB7XG4gIDxpb24tZmFiIFt2ZXJ0aWNhbF09XCJ2ZXJ0aWNhbFwiIFtob3Jpem9udGFsXT1cImhvcml6b250YWxcIiBbZWRnZV09XCJlZGdlXCI+XG4gICAgPGlvbi1mYWItYnV0dG9uIGNvbG9yPVwiZGFya1wiIHNpemU9XCJzbWFsbFwiIChjbGljayk9XCJzaG93U3RhdHVzKClcIj5cbiAgICAgIDwhLS0gT0ZGTElORSAtLT5cbiAgICAgIEBpZiAoX29mZmxpbmUuaXNPZmZsaW5lKCkpIHtcbiAgICAgICAgPGlvbi1pY29uIG5hbWU9XCJhaXJwbGFuZVwiIC8+XG4gICAgICB9XG4gICAgICA8IS0tIFNZTkNIUk9OSVNJTkcgLS0+XG4gICAgICBAaWYgKF9vZmZsaW5lLmlzT25saW5lKCkgJiYgX29mZmxpbmUuc3luY2hyb25pemluZykge1xuICAgICAgICA8aW9uLWljb24gbmFtZT1cInN5bmNcIiAvPlxuICAgICAgfVxuICAgICAgPCEtLSBORUVEIE1BTkFMIFNZTkNIUk9OSVNBVElPTiAtLT5cbiAgICAgIEBpZiAoX29mZmxpbmUuaXNPbmxpbmUoKSAmJiBfb2ZmbGluZS5yZXF1aXJlc01hbnVhbENvbmZpcm1hdGlvbikge1xuICAgICAgICA8aW9uLWljb24gbmFtZT1cInBhdXNlXCIgLz5cbiAgICAgIH1cbiAgICA8L2lvbi1mYWItYnV0dG9uPlxuICA8L2lvbi1mYWI+XG59XG4iXX0=
|