incyclist-services 1.0.56 → 1.0.58
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/lib/api/index.d.ts +1 -0
- package/lib/api/index.js +1 -0
- package/lib/api/repository/json/index.d.ts +9 -7
- package/lib/api/repository/json/index.js +34 -21
- package/lib/api/repository/types.d.ts +12 -4
- package/lib/api/repository/types.js +4 -0
- package/lib/devices/pairing/service.js +10 -3
- package/lib/devices/ride/service.d.ts +4 -0
- package/lib/devices/ride/service.js +65 -4
- package/lib/routes/base/api/index.d.ts +2 -1
- package/lib/routes/base/api/index.js +9 -7
- package/lib/routes/base/api/types.d.ts +17 -0
- package/lib/routes/base/types/index.d.ts +2 -2
- package/lib/routes/list/FreeRideCard.d.ts +8 -0
- package/lib/routes/list/FreeRideCard.js +11 -0
- package/lib/routes/list/service.d.ts +36 -11
- package/lib/routes/list/service.js +356 -61
- package/lib/routes/list/types.d.ts +47 -7
- package/lib/utils/geo.js +4 -2
- package/package.json +2 -2
package/lib/api/index.d.ts
CHANGED
package/lib/api/index.js
CHANGED
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./rest/index"), exports);
|
|
18
18
|
__exportStar(require("./rest/types"), exports);
|
|
19
|
+
__exportStar(require("./repository"), exports);
|
|
@@ -1,19 +1,21 @@
|
|
|
1
1
|
import { EventLogger } from "gd-eventlog";
|
|
2
|
-
import {
|
|
2
|
+
import { IJsonRepositoryBinding, JSONObject, JsonAccess } from "../types";
|
|
3
3
|
export declare class JsonRepository {
|
|
4
4
|
protected static _instances: {
|
|
5
5
|
[x: string]: JsonRepository;
|
|
6
6
|
};
|
|
7
|
-
protected static _defaultBinding:
|
|
7
|
+
protected static _defaultBinding: IJsonRepositoryBinding;
|
|
8
8
|
static create(repoName: string): JsonRepository;
|
|
9
|
-
static setBinding(binding:
|
|
10
|
-
protected binding:
|
|
9
|
+
static setBinding(binding: IJsonRepositoryBinding): void;
|
|
10
|
+
protected binding: IJsonRepositoryBinding;
|
|
11
11
|
protected name: string;
|
|
12
12
|
protected db: string;
|
|
13
13
|
protected logger: EventLogger;
|
|
14
|
-
|
|
14
|
+
protected access: JsonAccess;
|
|
15
|
+
constructor(repoName: string, binding?: IJsonRepositoryBinding);
|
|
16
|
+
getName(): string;
|
|
17
|
+
write(objectName: string, data: JSONObject): Promise<boolean>;
|
|
18
|
+
read(objectName: string): Promise<JSONObject>;
|
|
15
19
|
protected open(): Promise<boolean>;
|
|
16
20
|
protected close(): Promise<boolean>;
|
|
17
|
-
protected write(objectName: string, data: JSONObject): Promise<boolean>;
|
|
18
|
-
protected read(objectName: string): Promise<JSONObject>;
|
|
19
21
|
}
|
|
@@ -26,16 +26,48 @@ class JsonRepository {
|
|
|
26
26
|
this.binding = binding || JsonRepository._defaultBinding;
|
|
27
27
|
this.logger = new gd_eventlog_1.EventLogger(`Repo-${this.name}`);
|
|
28
28
|
}
|
|
29
|
+
getName() {
|
|
30
|
+
return this.name;
|
|
31
|
+
}
|
|
32
|
+
write(objectName, data) {
|
|
33
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
34
|
+
yield this.open();
|
|
35
|
+
const success = yield this.access.write(objectName, data);
|
|
36
|
+
if (!success) {
|
|
37
|
+
}
|
|
38
|
+
return success;
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
read(objectName) {
|
|
42
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
43
|
+
yield this.open();
|
|
44
|
+
try {
|
|
45
|
+
const data = yield this.access.read(objectName);
|
|
46
|
+
if (!data) {
|
|
47
|
+
}
|
|
48
|
+
return data;
|
|
49
|
+
}
|
|
50
|
+
catch (err) {
|
|
51
|
+
}
|
|
52
|
+
});
|
|
53
|
+
}
|
|
29
54
|
open() {
|
|
30
55
|
return __awaiter(this, void 0, void 0, function* () {
|
|
56
|
+
if (this.access)
|
|
57
|
+
return true;
|
|
31
58
|
if (!this.binding)
|
|
32
59
|
throw new Error('no binding specified');
|
|
33
60
|
try {
|
|
34
61
|
const existing = yield this.binding.get(this.name);
|
|
35
62
|
if (existing) {
|
|
63
|
+
this.access = existing;
|
|
36
64
|
return true;
|
|
37
65
|
}
|
|
38
|
-
|
|
66
|
+
const access = yield this.binding.create(this.name);
|
|
67
|
+
if (!access)
|
|
68
|
+
return false;
|
|
69
|
+
this.access = access;
|
|
70
|
+
return true;
|
|
39
71
|
}
|
|
40
72
|
catch (err) {
|
|
41
73
|
return false;
|
|
@@ -47,29 +79,10 @@ class JsonRepository {
|
|
|
47
79
|
if (!this.binding)
|
|
48
80
|
throw new Error('no binding specified');
|
|
49
81
|
this.binding.release(this.name);
|
|
82
|
+
this.access = null;
|
|
50
83
|
return true;
|
|
51
84
|
});
|
|
52
85
|
}
|
|
53
|
-
write(objectName, data) {
|
|
54
|
-
if (!this.binding)
|
|
55
|
-
throw new Error('no binding specified');
|
|
56
|
-
const success = this.binding.write(objectName, data);
|
|
57
|
-
if (!success) {
|
|
58
|
-
}
|
|
59
|
-
return success;
|
|
60
|
-
}
|
|
61
|
-
read(objectName) {
|
|
62
|
-
if (!this.binding)
|
|
63
|
-
throw new Error('no binding specified');
|
|
64
|
-
try {
|
|
65
|
-
const data = this.binding.read(objectName);
|
|
66
|
-
if (!data) {
|
|
67
|
-
}
|
|
68
|
-
return data;
|
|
69
|
-
}
|
|
70
|
-
catch (err) {
|
|
71
|
-
}
|
|
72
|
-
}
|
|
73
86
|
}
|
|
74
87
|
exports.JsonRepository = JsonRepository;
|
|
75
88
|
JsonRepository._instances = {};
|
|
@@ -1,10 +1,18 @@
|
|
|
1
1
|
export type JSONObject = string | number | boolean | {
|
|
2
2
|
[x: string]: JSONObject;
|
|
3
3
|
} | Array<JSONObject>;
|
|
4
|
-
export
|
|
5
|
-
create(name: string): Promise<boolean>;
|
|
6
|
-
get(name: string): Promise<boolean>;
|
|
7
|
-
release(name: string): Promise<boolean>;
|
|
4
|
+
export type JsonAccess = {
|
|
8
5
|
read(resourceName: string): Promise<JSONObject>;
|
|
9
6
|
write(resourceName: string, data: JSONObject): Promise<boolean>;
|
|
7
|
+
delete(resourceName: string): Promise<boolean>;
|
|
8
|
+
};
|
|
9
|
+
export interface IJsonRepositoryBinding {
|
|
10
|
+
create(name: string): Promise<JsonAccess | null>;
|
|
11
|
+
get(name: string): Promise<JsonAccess | null>;
|
|
12
|
+
release(name: string): Promise<boolean>;
|
|
13
|
+
}
|
|
14
|
+
export declare abstract class AbstractJsonRepositoryBinding implements IJsonRepositoryBinding {
|
|
15
|
+
abstract create(name: string): Promise<JsonAccess | null>;
|
|
16
|
+
abstract get(name: string): Promise<JsonAccess | null>;
|
|
17
|
+
abstract release(name: string): Promise<boolean>;
|
|
10
18
|
}
|
|
@@ -198,12 +198,13 @@ class DevicePairingService extends service_2.IncyclistService {
|
|
|
198
198
|
const c = this.getCapability(capability);
|
|
199
199
|
if (cntSelected === 1 && c.selected === udid) {
|
|
200
200
|
const adapter = this.getDeviceAdapter(udid);
|
|
201
|
-
adapter
|
|
201
|
+
if (adapter)
|
|
202
|
+
adapter.stop();
|
|
202
203
|
}
|
|
203
204
|
if (deleteAll) {
|
|
204
205
|
const adapter = this.getDeviceAdapter(udid);
|
|
205
206
|
const capabilities = adapter.getCapabilities();
|
|
206
|
-
capabilities.forEach((c, idx) => {
|
|
207
|
+
capabilities === null || capabilities === void 0 ? void 0 : capabilities.forEach((c, idx) => {
|
|
207
208
|
const shouldEmit = (idx === capabilities.length - 1);
|
|
208
209
|
this.deleteCapabilityDevice(c, udid, shouldEmit);
|
|
209
210
|
});
|
|
@@ -732,7 +733,7 @@ class DevicePairingService extends service_2.IncyclistService {
|
|
|
732
733
|
run(props = {}) {
|
|
733
734
|
return __awaiter(this, void 0, void 0, function* () {
|
|
734
735
|
this.emit('run');
|
|
735
|
-
if (this.isPairing() || this.isScanning()
|
|
736
|
+
if ((this.isPairing() || this.isScanning()) && !this.state.waiting) {
|
|
736
737
|
yield this._stop();
|
|
737
738
|
}
|
|
738
739
|
if (this.state.stopRequested || this.state.stopped) {
|
|
@@ -847,6 +848,10 @@ class DevicePairingService extends service_2.IncyclistService {
|
|
|
847
848
|
this.state.tsPrevStart = Date.now();
|
|
848
849
|
if (this.isScanning() && this.state.scan.preparing !== preparing)
|
|
849
850
|
return;
|
|
851
|
+
this.logEvent({ message: 'Stopping Adapters', interfaces: interfaces.join(','), props });
|
|
852
|
+
const stopPromises = [];
|
|
853
|
+
interfaces.forEach(i => stopPromises.push(this.stopAdaptersOnInterface(i)));
|
|
854
|
+
yield Promise.allSettled(stopPromises);
|
|
850
855
|
this.logEvent({ message: 'Start Scanning', interfaces: interfaces.join(','), props });
|
|
851
856
|
this.initScanningCallbacks();
|
|
852
857
|
const timeout = props.enforcedScan ? 1000 * 60 * 60 : undefined;
|
|
@@ -1016,6 +1021,8 @@ class DevicePairingService extends service_2.IncyclistService {
|
|
|
1016
1021
|
stopAdaptersWithCapability(capability, udid) {
|
|
1017
1022
|
return __awaiter(this, void 0, void 0, function* () {
|
|
1018
1023
|
const c = this.getCapability(capability);
|
|
1024
|
+
if (!c)
|
|
1025
|
+
return;
|
|
1019
1026
|
const { adapters = [], capabilities } = this.state;
|
|
1020
1027
|
const maxRetries = 3;
|
|
1021
1028
|
let target = udid ?
|
|
@@ -32,6 +32,10 @@ export declare class DeviceRideService extends EventEmitter {
|
|
|
32
32
|
startCheck(filter: RideServiceCheckFilter): Promise<void>;
|
|
33
33
|
getAdapters(filter: RideServiceCheckFilter): AdapterRideInfo[];
|
|
34
34
|
setSerialPortInUse(adapter: IncyclistDeviceAdapter): void;
|
|
35
|
+
protected checkAntSameDeviceID(adapters: AdapterRideInfo[]): Array<{
|
|
36
|
+
udid: string;
|
|
37
|
+
info: AdapterInfo;
|
|
38
|
+
}>;
|
|
35
39
|
startAdapters(adapters: AdapterRideInfo[], startType: 'start' | 'check' | 'pair', props?: RideServiceDeviceProperties): Promise<boolean>;
|
|
36
40
|
start(props: RideServiceDeviceProperties): Promise<boolean>;
|
|
37
41
|
startRetry(props: RideServiceDeviceProperties): Promise<boolean>;
|
|
@@ -336,11 +336,39 @@ class DeviceRideService extends events_1.default {
|
|
|
336
336
|
serial.setInUse(device.getPort());
|
|
337
337
|
}
|
|
338
338
|
}
|
|
339
|
+
checkAntSameDeviceID(adapters) {
|
|
340
|
+
const antDevices = adapters.map((ai, idx) => (Object.assign(Object.assign({}, ai), { idx })))
|
|
341
|
+
.filter(ai => ai.adapter.getInterface() === 'ant')
|
|
342
|
+
.map(ai => ({ idx: ai.idx, deviceID: ai.adapter.getID(), capabilities: ai.capabilities, udid: ai.udid }));
|
|
343
|
+
const antDeviceIds = antDevices.map(di => di.deviceID);
|
|
344
|
+
const duplicateIds = antDeviceIds.filter((item, index) => antDeviceIds.indexOf(item) !== index);
|
|
345
|
+
const score = (capabilities) => {
|
|
346
|
+
let value = 0;
|
|
347
|
+
if (capabilities.includes(incyclist_devices_1.IncyclistCapability.Control))
|
|
348
|
+
value += 100;
|
|
349
|
+
if (capabilities.includes(incyclist_devices_1.IncyclistCapability.Power))
|
|
350
|
+
value += 50;
|
|
351
|
+
value += capabilities.length;
|
|
352
|
+
return value;
|
|
353
|
+
};
|
|
354
|
+
const duplicateDevices = antDevices.filter(di => duplicateIds.includes(di.deviceID)).sort((a, b) => score(b.capabilities) - score(a.capabilities));
|
|
355
|
+
const leading = duplicateDevices[0];
|
|
356
|
+
const duplicateAdapters = [];
|
|
357
|
+
duplicateDevices.forEach((di, i) => {
|
|
358
|
+
if (i == 0)
|
|
359
|
+
return;
|
|
360
|
+
duplicateAdapters.push({ udid: leading.udid, info: adapters[di.idx] });
|
|
361
|
+
});
|
|
362
|
+
return duplicateAdapters;
|
|
363
|
+
}
|
|
339
364
|
startAdapters(adapters, startType, props) {
|
|
340
365
|
return __awaiter(this, void 0, void 0, function* () {
|
|
341
366
|
const { forceErgMode, startPos, realityFactor, rideMode, route } = props || {};
|
|
367
|
+
const duplicates = this.checkAntSameDeviceID(adapters);
|
|
342
368
|
this.startPromises = adapters === null || adapters === void 0 ? void 0 : adapters.map((ai) => __awaiter(this, void 0, void 0, function* () {
|
|
343
369
|
var _a;
|
|
370
|
+
if (duplicates.find(dai => dai.info.udid === ai.udid))
|
|
371
|
+
return;
|
|
344
372
|
const startProps = (0, clone_1.default)(props || {});
|
|
345
373
|
if (startType === 'check' || startType === 'pair') {
|
|
346
374
|
startProps.timeout = 10000;
|
|
@@ -389,6 +417,9 @@ class DeviceRideService extends events_1.default {
|
|
|
389
417
|
.then((success) => __awaiter(this, void 0, void 0, function* () {
|
|
390
418
|
if (success) {
|
|
391
419
|
this.emit(`${startType}-success`, this.getAdapterStateInfo(ai));
|
|
420
|
+
if (duplicates.find(dai => dai.udid === ai.udid)) {
|
|
421
|
+
duplicates.forEach(dai => { this.emit(`${startType}-success`, this.getAdapterStateInfo(dai.info)); });
|
|
422
|
+
}
|
|
392
423
|
this.logEvent(Object.assign({ message: `${startType} ${sType} request finished` }, logProps));
|
|
393
424
|
if (startType === 'check')
|
|
394
425
|
yield ai.adapter.pause().catch(console.log);
|
|
@@ -400,6 +431,9 @@ class DeviceRideService extends events_1.default {
|
|
|
400
431
|
}
|
|
401
432
|
else {
|
|
402
433
|
this.emit(`${startType}-error`, this.getAdapterStateInfo(ai));
|
|
434
|
+
if (duplicates.find(dai => dai.udid === ai.udid)) {
|
|
435
|
+
duplicates.forEach(dai => { this.emit(`${startType}-error`, this.getAdapterStateInfo(dai.info)); });
|
|
436
|
+
}
|
|
403
437
|
this.logEvent(Object.assign({ message: `${startType} ${sType} request failed` }, logProps));
|
|
404
438
|
if (startType === 'check' || startType === 'pair')
|
|
405
439
|
yield ai.adapter.stop().catch(console.log);
|
|
@@ -411,6 +445,9 @@ class DeviceRideService extends events_1.default {
|
|
|
411
445
|
ai.isStarted = false;
|
|
412
446
|
this.logEvent(Object.assign(Object.assign({ message: `${startType} ${sType} request failed` }, logProps), { reason: err.message }));
|
|
413
447
|
this.emit(`${startType}-error`, this.getAdapterStateInfo(ai), err);
|
|
448
|
+
if (duplicates.find(dai => dai.udid === ai.udid)) {
|
|
449
|
+
duplicates.forEach(dai => { this.emit(`${startType}-error`, this.getAdapterStateInfo(dai.info)); });
|
|
450
|
+
}
|
|
414
451
|
if (startType === 'check' || startType === 'pair') {
|
|
415
452
|
yield ai.adapter.stop().catch(console.log);
|
|
416
453
|
}
|
|
@@ -529,10 +566,29 @@ class DeviceRideService extends events_1.default {
|
|
|
529
566
|
this.verifySelected(selectedDevices, incyclist_devices_1.IncyclistCapability.Speed);
|
|
530
567
|
this.verifySelected(selectedDevices, incyclist_devices_1.IncyclistCapability.Cadence);
|
|
531
568
|
this.verifySelected(selectedDevices, incyclist_devices_1.IncyclistCapability.Power);
|
|
532
|
-
const
|
|
533
|
-
|
|
534
|
-
|
|
535
|
-
|
|
569
|
+
const duplicates = this.checkAntSameDeviceID(adapters);
|
|
570
|
+
const toBeReplaced = duplicates.filter(dai => dai.udid === adapterInfo.udid).map(dai => dai.info.udid);
|
|
571
|
+
let enabledCapabilities = [];
|
|
572
|
+
if (this.simulatorEnforced) {
|
|
573
|
+
enabledCapabilities = [incyclist_devices_1.IncyclistCapability.Control, incyclist_devices_1.IncyclistCapability.Power, incyclist_devices_1.IncyclistCapability.Speed, incyclist_devices_1.IncyclistCapability.HeartRate, incyclist_devices_1.IncyclistCapability.Cadence];
|
|
574
|
+
}
|
|
575
|
+
else if (duplicates.length > 0 && duplicates.find(d => d.udid === adapterInfo.udid)) {
|
|
576
|
+
const selected = (0, clone_1.default)(selectedDevices);
|
|
577
|
+
selected.forEach(cd => {
|
|
578
|
+
if (toBeReplaced.includes(cd.selected))
|
|
579
|
+
cd.selected = adapterInfo.udid;
|
|
580
|
+
});
|
|
581
|
+
selected.forEach;
|
|
582
|
+
selected.forEach(sd => {
|
|
583
|
+
const duplicate = duplicates.find(dai => dai.info.udid === sd.selected);
|
|
584
|
+
if (duplicate)
|
|
585
|
+
sd.selected = duplicate.udid;
|
|
586
|
+
});
|
|
587
|
+
enabledCapabilities = selected.map(c => c.capability);
|
|
588
|
+
}
|
|
589
|
+
else {
|
|
590
|
+
enabledCapabilities = selectedDevices.filter(sd => sd.selected === adapterInfo.udid).map(c => c.capability);
|
|
591
|
+
}
|
|
536
592
|
this.logEvent({ message: 'Data Update', device: adapterInfo.adapter.getName(), data, enabledCapabilities });
|
|
537
593
|
enabledCapabilities.forEach(capability => {
|
|
538
594
|
switch (capability) {
|
|
@@ -559,6 +615,11 @@ class DeviceRideService extends events_1.default {
|
|
|
559
615
|
}
|
|
560
616
|
});
|
|
561
617
|
this.emit('data', this.data, adapterInfo.udid);
|
|
618
|
+
if (toBeReplaced) {
|
|
619
|
+
toBeReplaced.forEach(udid => {
|
|
620
|
+
this.emit('data', this.data, udid);
|
|
621
|
+
});
|
|
622
|
+
}
|
|
562
623
|
}
|
|
563
624
|
sendUpdate(request) {
|
|
564
625
|
const adapters = this.getAdapterList();
|
|
@@ -12,7 +12,8 @@ export default class IncyclistRoutesApi {
|
|
|
12
12
|
protected getApi(): AxiosInstance;
|
|
13
13
|
protected getBaseUrl(): any;
|
|
14
14
|
getRouteDescriptions(query: RouteDescriptionQuery): Promise<Array<RouteApiDescription>>;
|
|
15
|
-
|
|
15
|
+
static verify(route: any): void;
|
|
16
|
+
protected static fixMissingRouteDistances(points: Array<RoutePoint>): void;
|
|
16
17
|
getRouteDetails(routeId: string): Promise<RouteApiDetail>;
|
|
17
18
|
reload(): Promise<any>;
|
|
18
19
|
protected _get(url: string, ...args: any[]): Promise<import("axios").AxiosResponse<any, any>>;
|
|
@@ -25,7 +25,6 @@ class IncyclistRoutesApi {
|
|
|
25
25
|
logError(err, fn, logInfo) {
|
|
26
26
|
const args = logInfo || {};
|
|
27
27
|
this.logger.logEvent(Object.assign({ message: 'Error', error: err.message, fn }, args));
|
|
28
|
-
console.log(err);
|
|
29
28
|
}
|
|
30
29
|
getApi() {
|
|
31
30
|
if (!this.api) {
|
|
@@ -53,7 +52,14 @@ class IncyclistRoutesApi {
|
|
|
53
52
|
}
|
|
54
53
|
});
|
|
55
54
|
}
|
|
56
|
-
|
|
55
|
+
static verify(route) {
|
|
56
|
+
if (route['decoded']) {
|
|
57
|
+
route.points = route['decoded'];
|
|
58
|
+
delete route['decoded'];
|
|
59
|
+
IncyclistRoutesApi.fixMissingRouteDistances(route.points);
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
static fixMissingRouteDistances(points) {
|
|
57
63
|
let routeDistance = 0;
|
|
58
64
|
points.forEach((p) => {
|
|
59
65
|
if (!p.routeDistance)
|
|
@@ -65,11 +71,7 @@ class IncyclistRoutesApi {
|
|
|
65
71
|
return __awaiter(this, void 0, void 0, function* () {
|
|
66
72
|
try {
|
|
67
73
|
const res = yield this._get(`/${routeId}`);
|
|
68
|
-
|
|
69
|
-
res.data.points = res.data['decoded'];
|
|
70
|
-
delete res.data['decoded'];
|
|
71
|
-
this.fixMissingRouteDistances(res.data.points);
|
|
72
|
-
}
|
|
74
|
+
IncyclistRoutesApi.verify(res.data);
|
|
73
75
|
return res.data;
|
|
74
76
|
}
|
|
75
77
|
catch (err) {
|
|
@@ -25,6 +25,23 @@ export type RouteApiDescription = {
|
|
|
25
25
|
type?: RouteType;
|
|
26
26
|
localizedTitle?: LocalizedText;
|
|
27
27
|
};
|
|
28
|
+
export type LegacyRouteGpxRepoDescription = {
|
|
29
|
+
id: string;
|
|
30
|
+
hash?: string;
|
|
31
|
+
routeHash?: string;
|
|
32
|
+
title: string;
|
|
33
|
+
private?: boolean;
|
|
34
|
+
distance?: number;
|
|
35
|
+
elevation?: number;
|
|
36
|
+
author?: {
|
|
37
|
+
id: string;
|
|
38
|
+
};
|
|
39
|
+
points?: {
|
|
40
|
+
id: string;
|
|
41
|
+
};
|
|
42
|
+
__v: number;
|
|
43
|
+
category?: RouteCategory;
|
|
44
|
+
};
|
|
28
45
|
export type RouteApiDetail = {
|
|
29
46
|
id: string;
|
|
30
47
|
routeId?: string;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export type RouteType = 'gpx' | 'video';
|
|
2
|
-
export type RouteCategory = 'Free' | 'Demo';
|
|
2
|
+
export type RouteCategory = 'Free' | 'Demo' | 'personal';
|
|
3
3
|
export type RouteState = 'prepared' | 'loading' | 'loaded' | 'error';
|
|
4
4
|
export type RouteProvider = {
|
|
5
5
|
name: string;
|
|
@@ -35,7 +35,7 @@ export type RoutePoint = {
|
|
|
35
35
|
lng: number;
|
|
36
36
|
routeDistance: number;
|
|
37
37
|
elevation: number;
|
|
38
|
-
slope
|
|
38
|
+
slope?: number;
|
|
39
39
|
};
|
|
40
40
|
export type RouteSegment = {
|
|
41
41
|
start: number;
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.FreeRideCard = void 0;
|
|
4
|
+
class FreeRideCard {
|
|
5
|
+
constructor(state, title) {
|
|
6
|
+
this.type = 'free-ride';
|
|
7
|
+
this.state = state;
|
|
8
|
+
this.title = title || 'Free Ride';
|
|
9
|
+
}
|
|
10
|
+
}
|
|
11
|
+
exports.FreeRideCard = FreeRideCard;
|
|
@@ -1,20 +1,24 @@
|
|
|
1
|
-
import { Page,
|
|
1
|
+
import { Page, InternalRouteListState, List, RouteInfo, Route, RouteListEntry, RouteListStartProps, RouteListData, RouteStartSettings, onRouteStatusUpdateCallback, onCarouselStateChangedCallback, RoutesDB } from "./types";
|
|
2
2
|
import IncyclistRoutesApi from "../base/api";
|
|
3
3
|
import { RouteApiDescription, RouteApiDetail } from "../base/api/types";
|
|
4
4
|
import { IncyclistService } from "../../base/service";
|
|
5
|
+
import { IJsonRepositoryBinding, JsonRepository } from "../../api";
|
|
5
6
|
type filterFn = (route: Route, idx: number, obj: Route[]) => boolean;
|
|
6
7
|
export declare class RouteListService extends IncyclistService {
|
|
7
8
|
protected static _instance: any;
|
|
8
|
-
static getInstance(binding?:
|
|
9
|
+
static getInstance(binding?: IJsonRepositoryBinding): RouteListService;
|
|
9
10
|
protected baseDir: string;
|
|
10
11
|
protected state: InternalRouteListState;
|
|
11
|
-
protected
|
|
12
|
-
protected
|
|
12
|
+
protected lists: Array<RouteListEntry>;
|
|
13
|
+
protected videosRepo: JsonRepository;
|
|
14
|
+
protected routesRepo: JsonRepository;
|
|
13
15
|
protected api: IncyclistRoutesApi;
|
|
14
|
-
|
|
15
|
-
|
|
16
|
+
protected routeDescriptions: RoutesDB;
|
|
17
|
+
constructor(binding?: IJsonRepositoryBinding);
|
|
18
|
+
setBinding(binding: IJsonRepositoryBinding): void;
|
|
19
|
+
protected getVideosRepo(): JsonRepository;
|
|
20
|
+
protected getRoutesRepo(): JsonRepository;
|
|
16
21
|
preload(carouselSize?: number): Promise<void>;
|
|
17
|
-
protected _preload(carouselSize?: number, detailsOnly?: boolean): Promise<void>;
|
|
18
22
|
load(props: {
|
|
19
23
|
list?: List;
|
|
20
24
|
loadFrom?: number;
|
|
@@ -22,9 +26,13 @@ export declare class RouteListService extends IncyclistService {
|
|
|
22
26
|
routeId?: string;
|
|
23
27
|
}): Promise<void>;
|
|
24
28
|
openRouteSelection(pageId: string, props: RouteListStartProps): RouteListData;
|
|
25
|
-
closeRouteSelection(
|
|
29
|
+
closeRouteSelection(pageId: string): void;
|
|
30
|
+
onResize(pageId: string): void;
|
|
26
31
|
openStartSettings(r: RouteInfo | string): RouteStartSettings;
|
|
27
32
|
cancelStartSettings(r: RouteInfo | string): {};
|
|
33
|
+
setCardUpdateHandler(pageId: string, r: RouteInfo | string, list: List, idx: number, onRouteStateChanged: onRouteStatusUpdateCallback, onCarouselStateChanged: onCarouselStateChangedCallback): void;
|
|
34
|
+
onCarouselInitialized(pageId: string, list: List, startIdx: number, visibleSize: number): void;
|
|
35
|
+
onCarouselUpdated(pageId: string, list: List, startIdx: number, visibleSize: number): void;
|
|
28
36
|
acceptStartSettings(r: RouteInfo | string, startSettings: RouteStartSettings): {};
|
|
29
37
|
getSelectedRoute(): RouteApiDetail;
|
|
30
38
|
getStartSettings(routeId?: string): RouteStartSettings;
|
|
@@ -32,6 +40,8 @@ export declare class RouteListService extends IncyclistService {
|
|
|
32
40
|
stopRide(r?: RouteInfo | string): {};
|
|
33
41
|
startDownload(routeId: any, onStatusUpdate: any): void;
|
|
34
42
|
cancelDownload(routeId: any): void;
|
|
43
|
+
protected _preload(carouselSize?: number, detailsOnly?: boolean): Promise<void>;
|
|
44
|
+
protected preloadList(list: List, carouselSize?: number): Promise<void>;
|
|
35
45
|
protected loadStartSettingsFromUserSettings(route: Route): {
|
|
36
46
|
startPos: number;
|
|
37
47
|
realityFactor: number;
|
|
@@ -54,13 +64,20 @@ export declare class RouteListService extends IncyclistService {
|
|
|
54
64
|
protected getRouteDescription(list: List, id: string): RouteInfo;
|
|
55
65
|
protected mergeDescription(local: RouteInfo, fromApi: RouteInfo): void;
|
|
56
66
|
protected mergeWithDetails(route: Route): void;
|
|
57
|
-
protected convertDescription(descr: RouteApiDescription): RouteInfo;
|
|
67
|
+
protected convertDescription(descr: RouteApiDescription, isLocal?: boolean): RouteInfo;
|
|
58
68
|
protected getListFromApiDesciption(description: RouteApiDescription): "selected" | "myRoutes" | "alternatives";
|
|
59
69
|
protected addRouteToList(list: List, route: Route): void;
|
|
60
70
|
protected getRouteList(list: List): Array<Route>;
|
|
71
|
+
protected getRouteLists(): Array<{
|
|
72
|
+
list: List;
|
|
73
|
+
title: string;
|
|
74
|
+
}>;
|
|
61
75
|
protected getRoute(criteria: string | filterFn): Route;
|
|
76
|
+
protected getAllRoutes(): Array<Route>;
|
|
62
77
|
protected stopAllRides(): void;
|
|
63
|
-
protected
|
|
78
|
+
protected addDescriptionsFromDB(descriptions: RoutesDB): void;
|
|
79
|
+
protected addDescriptionsFromRepo(descriptions: Array<RouteApiDescription>, repo?: JsonRepository): void;
|
|
80
|
+
protected addDescriptionsFromServer(descriptions: Array<RouteApiDescription>): void;
|
|
64
81
|
protected updateRouteTitle(data: RouteInfo, route: {
|
|
65
82
|
descr?: RouteApiDescription;
|
|
66
83
|
}): void;
|
|
@@ -69,10 +86,18 @@ export declare class RouteListService extends IncyclistService {
|
|
|
69
86
|
}): void;
|
|
70
87
|
protected getCountryPrefix(title?: string): string | undefined;
|
|
71
88
|
protected removeCountryPrefix(title?: string): string;
|
|
89
|
+
protected loadRouteDescriptionsFromRepo(): Promise<void>;
|
|
90
|
+
protected saveRouteDescriptions(): Promise<void>;
|
|
91
|
+
protected loadRouteDescriptionsFromServer(): Promise<void>;
|
|
72
92
|
protected loadRouteDescriptions(): Promise<void>;
|
|
73
|
-
protected loadRouteDetais(route: Route): Promise<
|
|
93
|
+
protected loadRouteDetais(route: Route): Promise<RouteInfo>;
|
|
94
|
+
saveRouteDetails(route: any): Promise<void>;
|
|
74
95
|
protected emitRouteUpdated(route: Route): void;
|
|
96
|
+
protected getListState(page: Page, list: List): import("./types").RouteListDateEntry;
|
|
75
97
|
private getRouteFromStartProps;
|
|
98
|
+
private isDescriptionsLoaded;
|
|
99
|
+
private decodePoints;
|
|
100
|
+
private encodePoints;
|
|
76
101
|
}
|
|
77
102
|
export declare const useRouteList: () => RouteListService;
|
|
78
103
|
export {};
|
|
@@ -18,6 +18,9 @@ const localization_1 = require("../base/utils/localization");
|
|
|
18
18
|
const service_1 = require("../../base/service");
|
|
19
19
|
const route_1 = require("../base/utils/route");
|
|
20
20
|
const settings_1 = require("../../settings");
|
|
21
|
+
const api_2 = require("../../api");
|
|
22
|
+
const clone_1 = __importDefault(require("../../utils/clone"));
|
|
23
|
+
const FreeRideCard_1 = require("./FreeRideCard");
|
|
21
24
|
class RouteListService extends service_1.IncyclistService {
|
|
22
25
|
static getInstance(binding) {
|
|
23
26
|
if (!RouteListService._instance)
|
|
@@ -28,52 +31,44 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
28
31
|
super('RouteList');
|
|
29
32
|
this.state = {
|
|
30
33
|
initialized: false,
|
|
31
|
-
pages: []
|
|
34
|
+
pages: [],
|
|
35
|
+
preloadDone: false
|
|
32
36
|
};
|
|
33
|
-
|
|
37
|
+
if (binding)
|
|
38
|
+
api_2.JsonRepository.setBinding(binding);
|
|
34
39
|
this.api = api_1.default.getInstance();
|
|
35
40
|
this.initRouteLists();
|
|
41
|
+
this.routeDescriptions = {};
|
|
36
42
|
}
|
|
37
43
|
setBinding(binding) {
|
|
38
44
|
if (!binding)
|
|
39
45
|
return;
|
|
40
|
-
|
|
46
|
+
api_2.JsonRepository.setBinding(binding);
|
|
41
47
|
this.state.initialized = true;
|
|
42
48
|
}
|
|
49
|
+
getVideosRepo() {
|
|
50
|
+
if (this.videosRepo)
|
|
51
|
+
return this.videosRepo;
|
|
52
|
+
this.videosRepo = api_2.JsonRepository.create('videos');
|
|
53
|
+
return this.videosRepo;
|
|
54
|
+
}
|
|
55
|
+
getRoutesRepo() {
|
|
56
|
+
if (this.routesRepo)
|
|
57
|
+
return this.routesRepo;
|
|
58
|
+
this.routesRepo = api_2.JsonRepository.create('routes');
|
|
59
|
+
return this.routesRepo;
|
|
60
|
+
}
|
|
43
61
|
preload(carouselSize = 5) {
|
|
44
62
|
return __awaiter(this, void 0, void 0, function* () {
|
|
45
|
-
if (this.state.loading)
|
|
46
|
-
|
|
63
|
+
if (this.state.loading || this.state.preloadDone)
|
|
64
|
+
return;
|
|
47
65
|
const promise = this._preload(carouselSize);
|
|
48
66
|
this.state.loading = { promise };
|
|
49
67
|
yield promise;
|
|
68
|
+
this.state.preloadDone = true;
|
|
50
69
|
this.state.loading = null;
|
|
51
70
|
});
|
|
52
71
|
}
|
|
53
|
-
_preload(carouselSize = 5, detailsOnly = false) {
|
|
54
|
-
return __awaiter(this, void 0, void 0, function* () {
|
|
55
|
-
this.logEvent({ message: 'preloading routes --' });
|
|
56
|
-
if (!detailsOnly) {
|
|
57
|
-
yield this.loadRouteDescriptions();
|
|
58
|
-
}
|
|
59
|
-
const promises = [];
|
|
60
|
-
this.routes.forEach(rle => {
|
|
61
|
-
var _a;
|
|
62
|
-
if (((_a = rle.routes) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
63
|
-
this.sort(rle.routes);
|
|
64
|
-
rle.routes.forEach((r, idx) => {
|
|
65
|
-
if (idx < Math.min(carouselSize, rle.routes.length)) {
|
|
66
|
-
const loader = this.loadRouteDetais(r);
|
|
67
|
-
promises.push(loader);
|
|
68
|
-
}
|
|
69
|
-
});
|
|
70
|
-
}
|
|
71
|
-
});
|
|
72
|
-
yield Promise.allSettled(promises);
|
|
73
|
-
this.emitPageUpdate();
|
|
74
|
-
this.logEvent({ message: 'preloading routes finished' });
|
|
75
|
-
});
|
|
76
|
-
}
|
|
77
72
|
load(props) {
|
|
78
73
|
return __awaiter(this, void 0, void 0, function* () {
|
|
79
74
|
const { routeId, list, loadFrom, loadTo } = props;
|
|
@@ -86,7 +81,7 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
86
81
|
if (list)
|
|
87
82
|
lists.push(list);
|
|
88
83
|
else
|
|
89
|
-
lists = this.
|
|
84
|
+
lists = this.lists.map(rle => rle.list);
|
|
90
85
|
lists.forEach(l => {
|
|
91
86
|
const routes = this.getRouteList(l);
|
|
92
87
|
for (let i = loadFrom; i < loadTo; i++) {
|
|
@@ -97,24 +92,39 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
97
92
|
}
|
|
98
93
|
openRouteSelection(pageId, props) {
|
|
99
94
|
const { language, visibleCards, visibleLists } = props;
|
|
100
|
-
this.logEvent({ message: '
|
|
95
|
+
this.logEvent({ message: 'openRouteSelection', pageId, language, visibleCards, visibleLists });
|
|
101
96
|
const existing = this.getPage(pageId);
|
|
102
97
|
if (existing) {
|
|
103
98
|
this.closeRouteSelection(pageId);
|
|
104
99
|
}
|
|
105
100
|
this.stopAllRides();
|
|
106
|
-
if (props.visibleCards) {
|
|
107
|
-
this._preload(props.visibleCards, true);
|
|
108
|
-
}
|
|
109
101
|
const page = this.registerPage(pageId, props);
|
|
102
|
+
if (!this.state.preloadDone)
|
|
103
|
+
this.preload(props.visibleCards || 5);
|
|
104
|
+
else
|
|
105
|
+
this.onResize(pageId);
|
|
110
106
|
return page.state;
|
|
111
107
|
}
|
|
112
|
-
closeRouteSelection(
|
|
113
|
-
const idx = this.getPage(
|
|
108
|
+
closeRouteSelection(pageId) {
|
|
109
|
+
const idx = this.getPage(pageId, true);
|
|
114
110
|
if (idx !== -1) {
|
|
115
111
|
this.state.pages.splice(idx, 1);
|
|
116
112
|
}
|
|
117
113
|
}
|
|
114
|
+
onResize(pageId) {
|
|
115
|
+
const page = this.getPage(pageId);
|
|
116
|
+
const routeIds = Object.keys(page.onCarouselStateChanged);
|
|
117
|
+
routeIds.forEach(id => {
|
|
118
|
+
var _a;
|
|
119
|
+
const route = this.getRoute(id);
|
|
120
|
+
const stateChange = (_a = page.onCarouselStateChanged[id]) === null || _a === void 0 ? void 0 : _a.onCarouselStateChanged;
|
|
121
|
+
if (stateChange)
|
|
122
|
+
stateChange({ initialized: true, visible: false });
|
|
123
|
+
const update = page.onRouteUpdate[id].onRouteStateChanged;
|
|
124
|
+
if (update)
|
|
125
|
+
update(route.data);
|
|
126
|
+
});
|
|
127
|
+
}
|
|
118
128
|
openStartSettings(r) {
|
|
119
129
|
var _a;
|
|
120
130
|
const route = this.getRouteFromStartProps(r);
|
|
@@ -146,6 +156,56 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
146
156
|
return {};
|
|
147
157
|
}
|
|
148
158
|
}
|
|
159
|
+
setCardUpdateHandler(pageId, r, list, idx, onRouteStateChanged, onCarouselStateChanged) {
|
|
160
|
+
const route = this.getRouteFromStartProps(r);
|
|
161
|
+
if (!route)
|
|
162
|
+
return;
|
|
163
|
+
const page = this.getPage(pageId);
|
|
164
|
+
if (!page)
|
|
165
|
+
return;
|
|
166
|
+
page.onRouteUpdate[route.id] = { idx, onRouteStateChanged };
|
|
167
|
+
page.onCarouselStateChanged[route.id] = { idx, onCarouselStateChanged };
|
|
168
|
+
}
|
|
169
|
+
onCarouselInitialized(pageId, list, startIdx, visibleSize) {
|
|
170
|
+
const page = this.getPage(pageId);
|
|
171
|
+
if (!page)
|
|
172
|
+
return;
|
|
173
|
+
const listState = this.getListState(page, list);
|
|
174
|
+
if (listState) {
|
|
175
|
+
listState.startIdx = startIdx;
|
|
176
|
+
listState.endIdx = startIdx + visibleSize - 1;
|
|
177
|
+
}
|
|
178
|
+
const routes = this.getRouteList(list);
|
|
179
|
+
routes.forEach((route) => {
|
|
180
|
+
const { idx, onCarouselStateChanged } = page.onCarouselStateChanged[route.id] || {};
|
|
181
|
+
const visible = listState !== undefined ? idx >= listState.startIdx && idx <= listState.endIdx : undefined;
|
|
182
|
+
if (onCarouselStateChanged)
|
|
183
|
+
onCarouselStateChanged({ initialized: true, visible });
|
|
184
|
+
if (visible && (route.data.state === 'prepared' || route.data.state === 'error')) {
|
|
185
|
+
this.loadRouteDetais(route);
|
|
186
|
+
}
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
onCarouselUpdated(pageId, list, startIdx, visibleSize) {
|
|
190
|
+
const page = this.getPage(pageId);
|
|
191
|
+
if (!page)
|
|
192
|
+
return;
|
|
193
|
+
const listState = this.getListState(page, list);
|
|
194
|
+
if (listState) {
|
|
195
|
+
listState.startIdx = startIdx;
|
|
196
|
+
listState.endIdx = startIdx + visibleSize - 1;
|
|
197
|
+
}
|
|
198
|
+
const routes = this.getRouteList(list);
|
|
199
|
+
routes.forEach((route) => {
|
|
200
|
+
const { idx, onCarouselStateChanged } = page.onCarouselStateChanged[route.id] || {};
|
|
201
|
+
const visible = listState !== undefined ? idx >= listState.startIdx && idx <= listState.endIdx : undefined;
|
|
202
|
+
if (onCarouselStateChanged)
|
|
203
|
+
onCarouselStateChanged({ initialized: true, visible });
|
|
204
|
+
if (visible && route.data.state === 'prepared' || route.data.state === 'error') {
|
|
205
|
+
this.loadRouteDetais(route);
|
|
206
|
+
}
|
|
207
|
+
});
|
|
208
|
+
}
|
|
149
209
|
acceptStartSettings(r, startSettings) {
|
|
150
210
|
var _a;
|
|
151
211
|
const route = this.getRouteFromStartProps(r);
|
|
@@ -192,6 +252,44 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
192
252
|
}
|
|
193
253
|
cancelDownload(routeId) {
|
|
194
254
|
}
|
|
255
|
+
_preload(carouselSize = 5, detailsOnly = false) {
|
|
256
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
257
|
+
if (!detailsOnly) {
|
|
258
|
+
yield this.loadRouteDescriptions();
|
|
259
|
+
}
|
|
260
|
+
this.emitPageUpdate();
|
|
261
|
+
const lists = this.getRouteLists().map(li => li.list);
|
|
262
|
+
lists.forEach((list) => {
|
|
263
|
+
this.preloadList(list, carouselSize);
|
|
264
|
+
});
|
|
265
|
+
this.logEvent({ message: 'preloading routes finished' });
|
|
266
|
+
});
|
|
267
|
+
}
|
|
268
|
+
preloadList(list, carouselSize = 5) {
|
|
269
|
+
var _a;
|
|
270
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
271
|
+
this.emitPageUpdate();
|
|
272
|
+
const promises = [];
|
|
273
|
+
const rle = this.lists.find(l => l.list === list);
|
|
274
|
+
if (((_a = rle.routes) === null || _a === void 0 ? void 0 : _a.length) > 0) {
|
|
275
|
+
this.sort(rle.routes);
|
|
276
|
+
let cntApi = 0;
|
|
277
|
+
rle.routes.forEach((r) => {
|
|
278
|
+
if (!r.data.isLocal) {
|
|
279
|
+
cntApi++;
|
|
280
|
+
}
|
|
281
|
+
if (r.data.isLocal || cntApi <= Math.min(carouselSize, rle.routes.length)) {
|
|
282
|
+
promises.push(this.loadRouteDetais(r));
|
|
283
|
+
}
|
|
284
|
+
});
|
|
285
|
+
}
|
|
286
|
+
console.log('~~~ DEBUG: during preload', promises.length);
|
|
287
|
+
Promise.allSettled(promises).then((res) => {
|
|
288
|
+
console.log('~~~ DEBUG: after preload', (0, clone_1.default)(this.state), (0, clone_1.default)(this.routeDescriptions), res);
|
|
289
|
+
this.saveRouteDescriptions();
|
|
290
|
+
});
|
|
291
|
+
});
|
|
292
|
+
}
|
|
195
293
|
loadStartSettingsFromUserSettings(route) {
|
|
196
294
|
let startPos = 0, realityFactor = 100, segment;
|
|
197
295
|
const { data } = route;
|
|
@@ -211,6 +309,10 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
211
309
|
if (prevRoutePosition !== null) {
|
|
212
310
|
startPos = prevRoutePosition;
|
|
213
311
|
}
|
|
312
|
+
if (data.videoFormat === 'avi') {
|
|
313
|
+
startPos = 0;
|
|
314
|
+
segment = undefined;
|
|
315
|
+
}
|
|
214
316
|
return { startPos, realityFactor, segment };
|
|
215
317
|
}
|
|
216
318
|
writeStartSettingsToUserSettings(route, startSettings) {
|
|
@@ -240,15 +342,15 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
240
342
|
}
|
|
241
343
|
emitPageUpdate() {
|
|
242
344
|
this.state.pages.forEach(p => {
|
|
243
|
-
|
|
244
|
-
p.onStatusUpdate(state);
|
|
345
|
+
p.state = this.getPageState(p.id);
|
|
346
|
+
p.onStatusUpdate(p.state);
|
|
245
347
|
});
|
|
246
348
|
}
|
|
247
349
|
initRouteLists() {
|
|
248
|
-
this.
|
|
249
|
-
this.
|
|
250
|
-
this.
|
|
251
|
-
this.
|
|
350
|
+
this.lists = [];
|
|
351
|
+
this.lists.push({ list: "myRoutes", routes: [] });
|
|
352
|
+
this.lists.push({ list: "selected", routes: [] });
|
|
353
|
+
this.lists.push({ list: "alternatives", routes: [] });
|
|
252
354
|
}
|
|
253
355
|
getPageState(pageId, lang) {
|
|
254
356
|
var _a;
|
|
@@ -257,6 +359,11 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
257
359
|
const language = lang || ((_a = this.getPage(pageId)) === null || _a === void 0 ? void 0 : _a.language) || 'en';
|
|
258
360
|
const add = (list, listHeader) => {
|
|
259
361
|
const data = this.getRouteList(list);
|
|
362
|
+
if (list === 'myRoutes' && !data.find(r => r.data.type === 'free-ride')) {
|
|
363
|
+
const card = new FreeRideCard_1.FreeRideCard('loaded');
|
|
364
|
+
const route = { data: card, id: 'free-ride', };
|
|
365
|
+
data.unshift(route);
|
|
366
|
+
}
|
|
260
367
|
if ((data === null || data === void 0 ? void 0 : data.length) > 0) {
|
|
261
368
|
lists.push(this.getRouteListDataEntry(list, data, language, listHeader));
|
|
262
369
|
}
|
|
@@ -264,12 +371,13 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
264
371
|
add('myRoutes', 'My Routes');
|
|
265
372
|
add('selected', 'Selected For Me');
|
|
266
373
|
add('alternatives', 'Alternatives');
|
|
374
|
+
console.log('~~~ DEBUG:getPageState', state);
|
|
267
375
|
return state;
|
|
268
376
|
}
|
|
269
377
|
registerPage(pageId, props) {
|
|
270
378
|
const { onStatusUpdate, language = 'en' } = props;
|
|
271
379
|
const state = this.getPageState(pageId, language);
|
|
272
|
-
const page = { id: pageId, onStatusUpdate, language, state };
|
|
380
|
+
const page = { id: pageId, onStatusUpdate, onRouteUpdate: {}, onCarouselStateChanged: {}, language, state };
|
|
273
381
|
this.state.pages.push(page);
|
|
274
382
|
return page;
|
|
275
383
|
}
|
|
@@ -317,7 +425,9 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
317
425
|
local.distance = local.distance || details.distance;
|
|
318
426
|
local.elevation = local.elevation || details.elevation;
|
|
319
427
|
local.localizedTitle = local.localizedTitle || details.localizedTitle;
|
|
320
|
-
local.points
|
|
428
|
+
if (!local.points) {
|
|
429
|
+
local.points = details.points;
|
|
430
|
+
}
|
|
321
431
|
if (!local.hasGpx && details.points) {
|
|
322
432
|
local.hasGpx = true;
|
|
323
433
|
}
|
|
@@ -342,11 +452,12 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
342
452
|
}
|
|
343
453
|
route.data = local;
|
|
344
454
|
}
|
|
345
|
-
convertDescription(descr) {
|
|
455
|
+
convertDescription(descr, isLocal) {
|
|
346
456
|
const { id, title, localizedTitle, country, distance, elevation, category, provider, video, points } = descr;
|
|
347
|
-
const data = { state: 'prepared', id, title, localizedTitle, country, distance, elevation, provider, category };
|
|
457
|
+
const data = { type: 'route', state: 'prepared', id, title, localizedTitle, country, distance, elevation, provider, category };
|
|
348
458
|
data.hasVideo = false;
|
|
349
459
|
data.hasGpx = false;
|
|
460
|
+
data.isLocal = isLocal || false;
|
|
350
461
|
this.updateRouteCountry(data, { descr });
|
|
351
462
|
this.updateRouteTitle(data, { descr });
|
|
352
463
|
if (points)
|
|
@@ -366,10 +477,14 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
366
477
|
var _a;
|
|
367
478
|
let list;
|
|
368
479
|
if (description.type === 'gpx') {
|
|
369
|
-
|
|
480
|
+
if (description.category === 'personal')
|
|
481
|
+
return 'myRoutes';
|
|
482
|
+
list = description.category ? 'alternatives' : 'selected';
|
|
370
483
|
return list;
|
|
371
484
|
}
|
|
372
485
|
if (description.type === 'video') {
|
|
486
|
+
if (description.category === undefined || description.category === 'personal')
|
|
487
|
+
return 'myRoutes';
|
|
373
488
|
if ((_a = description.video) === null || _a === void 0 ? void 0 : _a.url) {
|
|
374
489
|
return 'selected';
|
|
375
490
|
}
|
|
@@ -382,28 +497,82 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
382
497
|
}
|
|
383
498
|
getRouteList(list) {
|
|
384
499
|
var _a;
|
|
385
|
-
return (_a = this.
|
|
500
|
+
return (_a = this.lists.find(rle => rle.list === list)) === null || _a === void 0 ? void 0 : _a.routes;
|
|
501
|
+
}
|
|
502
|
+
getRouteLists() {
|
|
503
|
+
const lists = [
|
|
504
|
+
{ list: 'myRoutes', title: 'My Routes' },
|
|
505
|
+
{ list: 'selected', title: 'Selected For Me' },
|
|
506
|
+
{ list: 'alternatives', title: 'Alternatives' }
|
|
507
|
+
];
|
|
508
|
+
return lists;
|
|
386
509
|
}
|
|
387
510
|
getRoute(criteria) {
|
|
388
511
|
let compareFn = criteria;
|
|
389
512
|
if (typeof criteria === 'string')
|
|
390
513
|
compareFn = v => v.id === criteria;
|
|
391
|
-
const lists = this.
|
|
514
|
+
const lists = this.lists;
|
|
392
515
|
let route = null;
|
|
393
516
|
for (let i = 0; i < lists.length && !route; i++) {
|
|
394
517
|
route = lists[i].routes.find(compareFn);
|
|
395
518
|
}
|
|
396
519
|
return route;
|
|
397
520
|
}
|
|
521
|
+
getAllRoutes() {
|
|
522
|
+
const lists = this.lists;
|
|
523
|
+
const routes = [];
|
|
524
|
+
for (let i = 0; i < lists.length; i++) {
|
|
525
|
+
routes.push(...lists[i].routes);
|
|
526
|
+
}
|
|
527
|
+
return routes;
|
|
528
|
+
}
|
|
398
529
|
stopAllRides() {
|
|
399
|
-
const lists = this.
|
|
530
|
+
const lists = this.lists;
|
|
400
531
|
for (let i = 0; i < lists.length; i++) {
|
|
401
532
|
lists[i].routes.forEach(r => r.startState = 'idle');
|
|
402
533
|
}
|
|
403
534
|
}
|
|
404
|
-
|
|
535
|
+
addDescriptionsFromDB(descriptions) {
|
|
536
|
+
const ids = Object.keys(descriptions);
|
|
537
|
+
const routes = ids.map(id => descriptions[id]);
|
|
538
|
+
this.routeDescriptions = descriptions;
|
|
539
|
+
routes.forEach((data) => {
|
|
540
|
+
data.state = "prepared";
|
|
541
|
+
this.addRouteToList(data.list, { data, id: data.id });
|
|
542
|
+
});
|
|
543
|
+
}
|
|
544
|
+
addDescriptionsFromRepo(descriptions, repo) {
|
|
545
|
+
const routes = descriptions;
|
|
546
|
+
if (repo) {
|
|
547
|
+
const type = repo.getName() === 'videos' ? 'video' : 'gpx';
|
|
548
|
+
routes.forEach(r => {
|
|
549
|
+
r.type = type;
|
|
550
|
+
});
|
|
551
|
+
}
|
|
552
|
+
const converted = routes
|
|
553
|
+
.map(this.convertDescription.bind(this));
|
|
554
|
+
converted.forEach((data, idx) => {
|
|
555
|
+
const list = this.getListFromApiDesciption(descriptions[idx]);
|
|
556
|
+
const existing = this.getRouteDescription(list, data.id);
|
|
557
|
+
if (existing) {
|
|
558
|
+
this.mergeDescription(existing, data);
|
|
559
|
+
}
|
|
560
|
+
else {
|
|
561
|
+
data.state = 'prepared';
|
|
562
|
+
data.isLocal = true;
|
|
563
|
+
const item = { id: data.id, data };
|
|
564
|
+
this.addRouteToList(list, item);
|
|
565
|
+
this.routeDescriptions[data.id] = Object.assign(Object.assign({}, data), { list });
|
|
566
|
+
}
|
|
567
|
+
});
|
|
568
|
+
}
|
|
569
|
+
addDescriptionsFromServer(descriptions) {
|
|
405
570
|
const converted = descriptions.map(this.convertDescription.bind(this));
|
|
406
571
|
converted.forEach((data, idx) => {
|
|
572
|
+
const existing = this.getRoute(data.id);
|
|
573
|
+
if (existing) {
|
|
574
|
+
return;
|
|
575
|
+
}
|
|
407
576
|
const list = this.getListFromApiDesciption(descriptions[idx]);
|
|
408
577
|
if (!list) {
|
|
409
578
|
this.logEvent({ message: 'Error', error: 'no list found for route', id: data.id, title: data.title });
|
|
@@ -415,8 +584,11 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
415
584
|
}
|
|
416
585
|
else {
|
|
417
586
|
data.state = 'prepared';
|
|
587
|
+
data.isLocal = false;
|
|
418
588
|
const item = { id: data.id, data };
|
|
419
589
|
this.addRouteToList(list, item);
|
|
590
|
+
this.routeDescriptions[data.id] = Object.assign(Object.assign({}, data), { list });
|
|
591
|
+
this.emitPageUpdate();
|
|
420
592
|
}
|
|
421
593
|
});
|
|
422
594
|
}
|
|
@@ -457,39 +629,153 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
457
629
|
return title.substring(3);
|
|
458
630
|
}
|
|
459
631
|
}
|
|
460
|
-
|
|
632
|
+
loadRouteDescriptionsFromRepo() {
|
|
633
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
634
|
+
if (Object.keys(this.routeDescriptions).length > 0) {
|
|
635
|
+
this.emitPageUpdate();
|
|
636
|
+
return;
|
|
637
|
+
}
|
|
638
|
+
const all = yield this.getRoutesRepo().read('settings');
|
|
639
|
+
if (!all) {
|
|
640
|
+
const videos = ((yield this.getVideosRepo().read('routes')) || []);
|
|
641
|
+
this.addDescriptionsFromRepo(videos, this.getVideosRepo());
|
|
642
|
+
const routes = ((yield this.getRoutesRepo().read('routes')) || []);
|
|
643
|
+
this.addDescriptionsFromRepo(routes, this.getRoutesRepo());
|
|
644
|
+
}
|
|
645
|
+
else {
|
|
646
|
+
const ids = Object.keys(all);
|
|
647
|
+
ids.forEach(id => {
|
|
648
|
+
const r = all[id];
|
|
649
|
+
if (typeof r.points === 'string') {
|
|
650
|
+
this.decodePoints(r);
|
|
651
|
+
}
|
|
652
|
+
if (!Array.isArray(r.points))
|
|
653
|
+
delete r.points;
|
|
654
|
+
});
|
|
655
|
+
console.log('~~~ DEBUG:', all);
|
|
656
|
+
this.addDescriptionsFromDB(all);
|
|
657
|
+
}
|
|
658
|
+
this.saveRouteDescriptions();
|
|
659
|
+
});
|
|
660
|
+
}
|
|
661
|
+
saveRouteDescriptions() {
|
|
461
662
|
return __awaiter(this, void 0, void 0, function* () {
|
|
462
|
-
const
|
|
463
|
-
const
|
|
464
|
-
|
|
465
|
-
|
|
663
|
+
const ids = Object.keys(this.routeDescriptions);
|
|
664
|
+
const data = ids.map(id => {
|
|
665
|
+
const r = this.routeDescriptions[id];
|
|
666
|
+
if (r.points)
|
|
667
|
+
this.encodePoints(r);
|
|
668
|
+
return Object.assign({}, r);
|
|
669
|
+
});
|
|
670
|
+
yield this.getRoutesRepo().write('settings', data);
|
|
671
|
+
});
|
|
672
|
+
}
|
|
673
|
+
loadRouteDescriptionsFromServer() {
|
|
674
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
675
|
+
const enrichApi = (v, type) => (Object.assign({ type }, v));
|
|
676
|
+
const api = [
|
|
677
|
+
this.api.getRouteDescriptions({ type: 'gpx' }).then(v => v.map(e => enrichApi(e, 'gpx'))),
|
|
678
|
+
this.api.getRouteDescriptions({ type: 'video' }).then(v => v.map(e => enrichApi(e, 'video')))
|
|
466
679
|
];
|
|
467
|
-
const res = yield Promise.allSettled(
|
|
680
|
+
const res = yield Promise.allSettled(api);
|
|
468
681
|
res.forEach(p => {
|
|
469
682
|
if (p.status === 'fulfilled') {
|
|
470
|
-
this.
|
|
683
|
+
this.addDescriptionsFromServer(p.value);
|
|
471
684
|
}
|
|
472
685
|
});
|
|
473
686
|
});
|
|
474
687
|
}
|
|
688
|
+
loadRouteDescriptions() {
|
|
689
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
690
|
+
console.log('~~~ DEBUG:loadRouteDescriptions', Object.keys(this.routeDescriptions));
|
|
691
|
+
yield this.loadRouteDescriptionsFromRepo();
|
|
692
|
+
this.emitPageUpdate();
|
|
693
|
+
if (this.isDescriptionsLoaded()) {
|
|
694
|
+
yield this.loadRouteDescriptionsFromServer();
|
|
695
|
+
this.emitPageUpdate();
|
|
696
|
+
this.saveRouteDescriptions();
|
|
697
|
+
}
|
|
698
|
+
else {
|
|
699
|
+
this.loadRouteDescriptionsFromServer().then(() => {
|
|
700
|
+
this.emitPageUpdate();
|
|
701
|
+
});
|
|
702
|
+
}
|
|
703
|
+
});
|
|
704
|
+
}
|
|
475
705
|
loadRouteDetais(route) {
|
|
476
706
|
return __awaiter(this, void 0, void 0, function* () {
|
|
477
|
-
if (route.data.state === 'loaded')
|
|
707
|
+
if (route.data.state === 'loaded' || route.data.state === 'loading')
|
|
478
708
|
return;
|
|
479
709
|
try {
|
|
480
710
|
route.data.state = 'loading';
|
|
481
|
-
|
|
711
|
+
this.emitRouteUpdated(route);
|
|
712
|
+
try {
|
|
713
|
+
route.details = route.data.hasVideo ?
|
|
714
|
+
yield this.getVideosRepo().read(route.id)
|
|
715
|
+
:
|
|
716
|
+
yield this.getRoutesRepo().read(route.id);
|
|
717
|
+
api_1.default.verify(route.details);
|
|
718
|
+
}
|
|
719
|
+
catch (err) {
|
|
720
|
+
console.log('~~~ DEBUG:error', route.data.title, route.data.isLocal, err);
|
|
721
|
+
if (route.data.isLocal)
|
|
722
|
+
throw err;
|
|
723
|
+
}
|
|
724
|
+
if (!route.details) {
|
|
725
|
+
route.details = yield this.api.getRouteDetails(route.id);
|
|
726
|
+
api_1.default.verify(route.details);
|
|
727
|
+
this.saveRouteDetails(route);
|
|
728
|
+
}
|
|
729
|
+
if (route.details.id !== route.data.id) {
|
|
730
|
+
route.data.state = 'error';
|
|
731
|
+
delete route.details;
|
|
732
|
+
return;
|
|
733
|
+
}
|
|
482
734
|
this.mergeWithDetails(route);
|
|
483
|
-
route.data.state = '
|
|
735
|
+
route.data.state = 'loaded';
|
|
484
736
|
this.emitRouteUpdated(route);
|
|
737
|
+
const { list } = this.routeDescriptions[route.id];
|
|
738
|
+
this.routeDescriptions[route.id] = Object.assign(Object.assign({}, route.data), { list });
|
|
739
|
+
return route.data;
|
|
485
740
|
}
|
|
486
741
|
catch (e) {
|
|
487
742
|
route.data.state = 'error';
|
|
743
|
+
this.emitRouteUpdated(route);
|
|
744
|
+
}
|
|
745
|
+
});
|
|
746
|
+
}
|
|
747
|
+
saveRouteDetails(route) {
|
|
748
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
749
|
+
try {
|
|
750
|
+
route.details = route.data.hasVideo ?
|
|
751
|
+
yield this.videosRepo.write(route.id, route.details)
|
|
752
|
+
:
|
|
753
|
+
yield this.routesRepo.write(route.id, route.details);
|
|
754
|
+
}
|
|
755
|
+
catch (err) {
|
|
756
|
+
if (route.data.isLocal)
|
|
757
|
+
throw err;
|
|
488
758
|
}
|
|
489
759
|
});
|
|
490
760
|
}
|
|
491
761
|
emitRouteUpdated(route) {
|
|
492
762
|
this.emit('route-update', route.id, route.data);
|
|
763
|
+
this.state.pages.forEach(page => {
|
|
764
|
+
try {
|
|
765
|
+
const { onRouteStateChanged } = page.onRouteUpdate[route.id] || {};
|
|
766
|
+
const { language } = page;
|
|
767
|
+
if (onRouteStateChanged) {
|
|
768
|
+
const data = (0, localization_1.getLocalizedData)(route.data, language);
|
|
769
|
+
onRouteStateChanged(data);
|
|
770
|
+
}
|
|
771
|
+
}
|
|
772
|
+
catch (err) {
|
|
773
|
+
console.log('~~~ DEBUG:Error', err);
|
|
774
|
+
}
|
|
775
|
+
});
|
|
776
|
+
}
|
|
777
|
+
getListState(page, list) {
|
|
778
|
+
return page === null || page === void 0 ? void 0 : page.state.lists.find(pl => pl.list === list);
|
|
493
779
|
}
|
|
494
780
|
getRouteFromStartProps(r) {
|
|
495
781
|
try {
|
|
@@ -507,6 +793,15 @@ class RouteListService extends service_1.IncyclistService {
|
|
|
507
793
|
return;
|
|
508
794
|
}
|
|
509
795
|
}
|
|
796
|
+
isDescriptionsLoaded() {
|
|
797
|
+
return Object.keys(this.routeDescriptions).length === 0;
|
|
798
|
+
}
|
|
799
|
+
decodePoints(r) {
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
encodePoints(r) {
|
|
803
|
+
return;
|
|
804
|
+
}
|
|
510
805
|
}
|
|
511
806
|
exports.RouteListService = RouteListService;
|
|
512
807
|
const useRouteList = () => RouteListService.getInstance();
|
|
@@ -12,10 +12,14 @@ export type RouteListStartProps = {
|
|
|
12
12
|
export type LocalizedText = {
|
|
13
13
|
[index: string]: string;
|
|
14
14
|
};
|
|
15
|
-
export type
|
|
15
|
+
export type CardType = 'route' | 'free-ride' | 'import';
|
|
16
|
+
export interface CardInfo {
|
|
17
|
+
type: CardType;
|
|
16
18
|
state: RouteState;
|
|
17
|
-
id?: string;
|
|
18
19
|
title?: string;
|
|
20
|
+
}
|
|
21
|
+
export interface RouteInfo extends CardInfo {
|
|
22
|
+
id?: string;
|
|
19
23
|
localizedTitle?: LocalizedText;
|
|
20
24
|
country?: string;
|
|
21
25
|
isLoop?: boolean;
|
|
@@ -23,6 +27,7 @@ export type RouteInfo = {
|
|
|
23
27
|
elevation?: number;
|
|
24
28
|
category?: RouteCategory;
|
|
25
29
|
provider?: RouteProvider;
|
|
30
|
+
isLocal?: boolean;
|
|
26
31
|
hasGpx?: boolean;
|
|
27
32
|
hasVideo?: boolean;
|
|
28
33
|
isDemo?: boolean;
|
|
@@ -30,14 +35,34 @@ export type RouteInfo = {
|
|
|
30
35
|
videoFormat?: string;
|
|
31
36
|
videoUrl?: string;
|
|
32
37
|
previewUrl?: string;
|
|
33
|
-
points?: Array<RoutePoint
|
|
38
|
+
points?: Array<RoutePoint> | string;
|
|
34
39
|
segments?: Array<RouteSegment>;
|
|
40
|
+
}
|
|
41
|
+
export interface RouteDBEntry extends RouteInfo {
|
|
42
|
+
list: List;
|
|
43
|
+
settings?: {
|
|
44
|
+
position?: number;
|
|
45
|
+
segment?: string;
|
|
46
|
+
realityFactor?: number;
|
|
47
|
+
};
|
|
48
|
+
cntStarts?: number;
|
|
49
|
+
lastStart?: number;
|
|
50
|
+
}
|
|
51
|
+
export type RoutesDB = {
|
|
52
|
+
[index: string]: RouteDBEntry;
|
|
35
53
|
};
|
|
36
54
|
export type RouteListDateEntry = {
|
|
37
55
|
list: List;
|
|
38
56
|
listHeader: string;
|
|
39
57
|
routes: Array<RouteInfo>;
|
|
58
|
+
startIdx?: number;
|
|
59
|
+
endIdx?: number;
|
|
40
60
|
};
|
|
61
|
+
export type onRouteStatusUpdateCallback = (route: RouteInfo) => void;
|
|
62
|
+
export type onCarouselStateChangedCallback = (state: {
|
|
63
|
+
initialized: boolean;
|
|
64
|
+
visible: boolean;
|
|
65
|
+
}) => void;
|
|
41
66
|
export type RouteListData = {
|
|
42
67
|
pageId: string;
|
|
43
68
|
lists: Array<RouteListDateEntry>;
|
|
@@ -59,6 +84,18 @@ export type Page = {
|
|
|
59
84
|
settingsState?: RouteSettingsState;
|
|
60
85
|
language: string;
|
|
61
86
|
onStatusUpdate: RouteListStatusUpdateCallback;
|
|
87
|
+
onRouteUpdate: {
|
|
88
|
+
[index: string]: {
|
|
89
|
+
idx: number;
|
|
90
|
+
onRouteStateChanged: onRouteStatusUpdateCallback;
|
|
91
|
+
};
|
|
92
|
+
};
|
|
93
|
+
onCarouselStateChanged: {
|
|
94
|
+
[index: string]: {
|
|
95
|
+
idx: number;
|
|
96
|
+
onCarouselStateChanged: onCarouselStateChangedCallback;
|
|
97
|
+
};
|
|
98
|
+
};
|
|
62
99
|
};
|
|
63
100
|
export interface LoadingState {
|
|
64
101
|
promise: any;
|
|
@@ -67,17 +104,20 @@ export interface InternalRouteListState {
|
|
|
67
104
|
initialized: boolean;
|
|
68
105
|
pages: Array<Page>;
|
|
69
106
|
loading?: LoadingState;
|
|
107
|
+
preloadDone: boolean;
|
|
70
108
|
}
|
|
71
109
|
export type RouteStartState = 'idle' | 'preparing' | 'selected' | 'started';
|
|
72
|
-
export type
|
|
110
|
+
export type Card<T> = {
|
|
73
111
|
id: string;
|
|
74
|
-
data:
|
|
112
|
+
data: T;
|
|
75
113
|
details?: RouteApiDetail;
|
|
76
114
|
startSettings?: RouteStartSettings;
|
|
77
115
|
startState?: RouteStartState;
|
|
78
116
|
};
|
|
79
|
-
export type
|
|
117
|
+
export type CardListEntry<T> = {
|
|
80
118
|
list: List;
|
|
81
|
-
routes: Array<
|
|
119
|
+
routes: Array<Card<T>>;
|
|
82
120
|
};
|
|
121
|
+
export type Route = Card<RouteInfo>;
|
|
122
|
+
export type RouteListEntry = CardListEntry<RouteInfo>;
|
|
83
123
|
export type List = 'myRoutes' | 'alternatives' | 'selected';
|
package/lib/utils/geo.js
CHANGED
|
@@ -47,9 +47,11 @@ const getPointAfter = (p1, p2, offset) => {
|
|
|
47
47
|
};
|
|
48
48
|
exports.getPointAfter = getPointAfter;
|
|
49
49
|
const getLatLng = (position) => {
|
|
50
|
-
if (Array.isArray(position))
|
|
50
|
+
if (Array.isArray(position)) {
|
|
51
51
|
return { lat: position[0], lng: position[1] };
|
|
52
|
-
|
|
52
|
+
}
|
|
53
|
+
if (position.lat !== undefined && position.lng !== undefined) {
|
|
53
54
|
return position;
|
|
55
|
+
}
|
|
54
56
|
};
|
|
55
57
|
exports.getLatLng = getLatLng;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-services",
|
|
3
|
-
"version": "1.0.
|
|
3
|
+
"version": "1.0.58",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"gd-eventlog": "^0.1.26"
|
|
6
6
|
},
|
|
@@ -39,7 +39,7 @@
|
|
|
39
39
|
},
|
|
40
40
|
"dependencies": {
|
|
41
41
|
"axios": "^1.6.1",
|
|
42
|
-
"incyclist-devices": "^2.1.
|
|
42
|
+
"incyclist-devices": "^2.1.24",
|
|
43
43
|
"uuid": "^9.0.0"
|
|
44
44
|
}
|
|
45
45
|
}
|