incyclist-services 1.7.59 → 1.7.60
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/cjs/maps/MapArea/options.js +12 -11
- package/lib/cjs/ride/display/service.js +32 -8
- package/lib/cjs/ride/page/service.js +2 -1
- package/lib/cjs/ride/route/FreeRideDisplayService.js +2 -2
- package/lib/cjs/ride/route/GpxDisplayService.js +5 -3
- package/lib/cjs/routes/free-ride/service.js +28 -3
- package/lib/esm/maps/MapArea/options.js +12 -11
- package/lib/esm/ride/display/service.js +32 -8
- package/lib/esm/ride/page/service.js +2 -1
- package/lib/esm/ride/route/FreeRideDisplayService.js +2 -2
- package/lib/esm/ride/route/GpxDisplayService.js +5 -3
- package/lib/esm/routes/free-ride/service.js +28 -3
- package/lib/types/maps/MapArea/options.d.ts +2 -2
- package/lib/types/maps/MapArea/types.d.ts +4 -0
- package/lib/types/ride/base/types.d.ts +2 -0
- package/lib/types/ride/display/service.d.ts +4 -2
- package/lib/types/ride/page/types.d.ts +1 -0
- package/lib/types/routes/free-ride/service.d.ts +2 -0
- package/package.json +2 -2
|
@@ -28,15 +28,16 @@ class OptionManager {
|
|
|
28
28
|
for (const segment of segments ?? []) {
|
|
29
29
|
try {
|
|
30
30
|
const path = segment.path;
|
|
31
|
-
const
|
|
31
|
+
const result = await this.getNextOptions(segment);
|
|
32
|
+
const opts = result.options;
|
|
32
33
|
if (opts?.length === 1) {
|
|
33
34
|
if (opts[0].id === segment.id) {
|
|
34
35
|
(0, utils_1.concatPaths)(path, opts[0].path, 'after', opts[0].id);
|
|
35
36
|
}
|
|
36
37
|
else {
|
|
37
38
|
let foundSameSegment = false;
|
|
38
|
-
opts[0].path.forEach((point
|
|
39
|
-
if (
|
|
39
|
+
opts[0].path.forEach((point) => {
|
|
40
|
+
if (point === opts[0].path[0])
|
|
40
41
|
return;
|
|
41
42
|
foundSameSegment = points.some(pAll => pAll.id === point.id);
|
|
42
43
|
});
|
|
@@ -58,7 +59,7 @@ class OptionManager {
|
|
|
58
59
|
async getNextOptions(from, props) {
|
|
59
60
|
try {
|
|
60
61
|
if (from?.id === undefined || from?.path === undefined || from?.path.length < 1) {
|
|
61
|
-
return [];
|
|
62
|
+
return { options: [], isValid: true };
|
|
62
63
|
}
|
|
63
64
|
const lastPoint = from.path.length > 0 ? from.path.at(-1) : undefined;
|
|
64
65
|
const fromWayId = lastPoint?.wayId ?? from.id;
|
|
@@ -68,7 +69,7 @@ class OptionManager {
|
|
|
68
69
|
const query = { id: from.id, path: from.path, map: map };
|
|
69
70
|
originalWay = this.getWay(query);
|
|
70
71
|
if (!originalWay) {
|
|
71
|
-
return [];
|
|
72
|
+
return { options: [], isValid: true };
|
|
72
73
|
}
|
|
73
74
|
}
|
|
74
75
|
const way = { ...originalWay, path: from.path };
|
|
@@ -77,13 +78,13 @@ class OptionManager {
|
|
|
77
78
|
if (way.path.length > 1)
|
|
78
79
|
location = way.path.at(-2);
|
|
79
80
|
else {
|
|
80
|
-
return [];
|
|
81
|
+
return { options: [], isValid: true };
|
|
81
82
|
}
|
|
82
83
|
}
|
|
83
84
|
const map = await this.service.load(location);
|
|
84
85
|
if (!map) {
|
|
85
86
|
if (!this.map?.isWithinBoundary(location))
|
|
86
|
-
return [];
|
|
87
|
+
return { options: [], isValid: true };
|
|
87
88
|
}
|
|
88
89
|
else {
|
|
89
90
|
this.setMap(map);
|
|
@@ -118,11 +119,11 @@ class OptionManager {
|
|
|
118
119
|
const fromNode = from.path?.at(-2);
|
|
119
120
|
options = options.filter(o => o.path.length > 0 && o.path[1].id !== fromNode.id);
|
|
120
121
|
}
|
|
121
|
-
return options;
|
|
122
|
+
return { options, isValid: true };
|
|
122
123
|
}
|
|
123
124
|
catch (err) {
|
|
124
125
|
this.logError(err, 'getNextOptions');
|
|
125
|
-
return [];
|
|
126
|
+
return { options: [], isValid: false };
|
|
126
127
|
}
|
|
127
128
|
}
|
|
128
129
|
async checkMinDistance(options, minDistance) {
|
|
@@ -130,8 +131,8 @@ class OptionManager {
|
|
|
130
131
|
if (option?.path?.length > 0) {
|
|
131
132
|
const distance = this.getDistance(option.path);
|
|
132
133
|
if (distance < minDistance) {
|
|
133
|
-
const
|
|
134
|
-
option.options =
|
|
134
|
+
const result = await this.getNextOptions(option, { minDistance: minDistance - distance });
|
|
135
|
+
option.options = result.options ?? [];
|
|
135
136
|
}
|
|
136
137
|
}
|
|
137
138
|
}
|
|
@@ -619,25 +619,30 @@ let RideDisplayService = (() => {
|
|
|
619
619
|
this.adjustCurrentStepDuration(time, newDuration);
|
|
620
620
|
this.updateActivityWorkout();
|
|
621
621
|
}
|
|
622
|
-
adjustPower(increase, large) {
|
|
622
|
+
adjustPower(increase, large, gearFallback = true) {
|
|
623
623
|
try {
|
|
624
624
|
if (this.getWorkoutRide().inUse()) {
|
|
625
625
|
const inc = large ? 5 : 1;
|
|
626
|
-
|
|
627
|
-
this.getWorkoutRide().powerUp(inc);
|
|
628
|
-
else
|
|
629
|
-
this.getWorkoutRide().powerDown(inc);
|
|
626
|
+
this.adjustWorkout(increase, inc);
|
|
630
627
|
}
|
|
631
628
|
else {
|
|
632
629
|
const sgn = increase ? 1 : -1;
|
|
633
630
|
const inc = large ? sgn * 50 : sgn * 5;
|
|
634
|
-
this.devicePowerUp(inc);
|
|
631
|
+
this.devicePowerUp(inc, gearFallback);
|
|
635
632
|
}
|
|
636
633
|
}
|
|
637
634
|
catch (err) {
|
|
638
635
|
this.logError(err, 'adjustPower');
|
|
639
636
|
}
|
|
640
637
|
}
|
|
638
|
+
adjustWorkout(increase, inc) {
|
|
639
|
+
if (this.getWorkoutRide().inUse()) {
|
|
640
|
+
if (increase)
|
|
641
|
+
this.getWorkoutRide().powerUp(inc);
|
|
642
|
+
else
|
|
643
|
+
this.getWorkoutRide().powerDown(inc);
|
|
644
|
+
}
|
|
645
|
+
}
|
|
641
646
|
adjustCurrentStepDuration(time, newDuration) {
|
|
642
647
|
let delta = 0;
|
|
643
648
|
this.actualWorkout?.steps?.forEach(s => {
|
|
@@ -845,7 +850,7 @@ let RideDisplayService = (() => {
|
|
|
845
850
|
devices.off('cycling-mode-toggle', h.toggleCyclingModeHandler);
|
|
846
851
|
delete this.startDeviceHandlers;
|
|
847
852
|
}
|
|
848
|
-
devicePowerUp(inc) {
|
|
853
|
+
devicePowerUp(inc, gearFallback = true) {
|
|
849
854
|
const device = this.getDeviceRide().getControlAdapter();
|
|
850
855
|
if (!device)
|
|
851
856
|
return;
|
|
@@ -861,9 +866,12 @@ let RideDisplayService = (() => {
|
|
|
861
866
|
if (Math.abs(gearDelta) > 1) {
|
|
862
867
|
gearDelta = Math.sign(gearDelta) * 5;
|
|
863
868
|
}
|
|
864
|
-
this.
|
|
869
|
+
this.gearChange(gearDelta);
|
|
865
870
|
}
|
|
866
871
|
}
|
|
872
|
+
gearChange(gearDelta) {
|
|
873
|
+
this.getRideModeService().sendUpdate({ gearDelta });
|
|
874
|
+
}
|
|
867
875
|
simulatorPowerUp(mode, powerInc) {
|
|
868
876
|
const simMode = mode.getSetting('mode');
|
|
869
877
|
let request = {};
|
|
@@ -985,6 +993,22 @@ let RideDisplayService = (() => {
|
|
|
985
993
|
this.adjustPower(true, duration > 1000);
|
|
986
994
|
else if (key === 'down')
|
|
987
995
|
this.adjustPower(false, duration > 1000);
|
|
996
|
+
else if (key == 'r-shift-up')
|
|
997
|
+
this.gearChange(1);
|
|
998
|
+
else if (key == 'r-shift-down')
|
|
999
|
+
this.gearChange(-1);
|
|
1000
|
+
else if (key == 'l-shift-up')
|
|
1001
|
+
this.gearChange(5);
|
|
1002
|
+
else if (key == 'l-shift-down')
|
|
1003
|
+
this.gearChange(-5);
|
|
1004
|
+
else if (key == 'y')
|
|
1005
|
+
this.adjustPower(true, duration > 1000, false);
|
|
1006
|
+
else if (key == 'b')
|
|
1007
|
+
this.adjustPower(false, duration > 1000, false);
|
|
1008
|
+
else if (key == 'a')
|
|
1009
|
+
this.forward();
|
|
1010
|
+
else if (key == 'z')
|
|
1011
|
+
this.backward();
|
|
988
1012
|
}
|
|
989
1013
|
startListeningForDeviceData() {
|
|
990
1014
|
const { deviceDataHandler } = this.startDeviceHandlers ?? {};
|
|
@@ -292,7 +292,8 @@ let RidePageService = (() => {
|
|
|
292
292
|
startOverlayProps: isStarting ? this.getRideDisplay().getStartOverlayProps() : null,
|
|
293
293
|
menuProps: this.menuProps,
|
|
294
294
|
rideView: props.rideView,
|
|
295
|
-
route: props.route
|
|
295
|
+
route: props.route,
|
|
296
|
+
displayObserver: props.displayObserver
|
|
296
297
|
};
|
|
297
298
|
return displayProps;
|
|
298
299
|
}
|
|
@@ -422,11 +422,11 @@ let FreeRideDisplayService = (() => {
|
|
|
422
422
|
this.logError(err, 'getNextOptions');
|
|
423
423
|
options = undefined;
|
|
424
424
|
}
|
|
425
|
-
if (!options?.length && !finished && !forStart) {
|
|
425
|
+
if (!options?.length && !finished && !forStart && !freeRide.isLastQueryValid()) {
|
|
426
426
|
this.logEvent({ message: 'no options available - retry in 3000ms', });
|
|
427
427
|
await (0, sleep_1.sleep)(3000);
|
|
428
428
|
}
|
|
429
|
-
} while (!options?.length && !finished && !forStart);
|
|
429
|
+
} while (!options?.length && !finished && !forStart && !freeRide.isLastQueryValid());
|
|
430
430
|
this.internalEmitter.off('stop-query', setFinished);
|
|
431
431
|
};
|
|
432
432
|
return new Promise(done => {
|
|
@@ -103,6 +103,8 @@ let GpxDisplayService = (() => {
|
|
|
103
103
|
displayPosition: this.mapLoaded ? null : this.position,
|
|
104
104
|
sideViews
|
|
105
105
|
};
|
|
106
|
+
if (this.isMobile()) {
|
|
107
|
+
}
|
|
106
108
|
return props;
|
|
107
109
|
}
|
|
108
110
|
getSatelliteViewProps() {
|
|
@@ -120,7 +122,7 @@ let GpxDisplayService = (() => {
|
|
|
120
122
|
}
|
|
121
123
|
getStartOverlayProps() {
|
|
122
124
|
const rideView = this.getRideView();
|
|
123
|
-
if (rideView === 'map') {
|
|
125
|
+
if (rideView === 'map' || this.isMobile()) {
|
|
124
126
|
return {
|
|
125
127
|
mapType: this.getRideViewName(),
|
|
126
128
|
mapState: 'Loaded'
|
|
@@ -134,7 +136,7 @@ let GpxDisplayService = (() => {
|
|
|
134
136
|
}
|
|
135
137
|
isStartRideCompleted() {
|
|
136
138
|
const rideView = this.getRideView();
|
|
137
|
-
if (rideView === 'map') {
|
|
139
|
+
if (rideView === 'map' || this.isMobile()) {
|
|
138
140
|
this.mapLoaded = true;
|
|
139
141
|
return true;
|
|
140
142
|
}
|
|
@@ -159,7 +161,7 @@ let GpxDisplayService = (() => {
|
|
|
159
161
|
}
|
|
160
162
|
getRideView() {
|
|
161
163
|
if (this.isMobile())
|
|
162
|
-
return '
|
|
164
|
+
return 'sv';
|
|
163
165
|
const rideView = this.getUserSettings().get('preferences.rideView', 'sv');
|
|
164
166
|
return rideView;
|
|
165
167
|
}
|
|
@@ -75,6 +75,7 @@ let FreeRideService = (() => {
|
|
|
75
75
|
selectedOption;
|
|
76
76
|
options;
|
|
77
77
|
currentSegment;
|
|
78
|
+
lastOptionsQueryValid = true;
|
|
78
79
|
constructor() {
|
|
79
80
|
super('FreeRide');
|
|
80
81
|
this.options = [];
|
|
@@ -137,7 +138,12 @@ let FreeRideService = (() => {
|
|
|
137
138
|
}
|
|
138
139
|
async loadNextOptions(from, forStart) {
|
|
139
140
|
const optionManager = (0, service_2.useMapArea)().getOptionManager();
|
|
140
|
-
|
|
141
|
+
const result = await optionManager.getNextOptions(from);
|
|
142
|
+
let opts = result.options;
|
|
143
|
+
this.lastOptionsQueryValid = result.isValid;
|
|
144
|
+
if (!result.isValid) {
|
|
145
|
+
return [];
|
|
146
|
+
}
|
|
141
147
|
opts = this.evaluateOptions(opts, from);
|
|
142
148
|
if (forStart)
|
|
143
149
|
await this.getNextLevelOptions(opts);
|
|
@@ -289,8 +295,11 @@ let FreeRideService = (() => {
|
|
|
289
295
|
let segment = o;
|
|
290
296
|
let done = false;
|
|
291
297
|
let isSingle = false;
|
|
298
|
+
let lastHandlerWasNoOption = false;
|
|
292
299
|
do {
|
|
293
|
-
const
|
|
300
|
+
const nextOptsResult = await optionManager.getNextOptions(segment);
|
|
301
|
+
const nextOpts = nextOptsResult.options;
|
|
302
|
+
const isValid = nextOptsResult.isValid;
|
|
294
303
|
const handleSingleOption = () => {
|
|
295
304
|
if (segmentUpdated)
|
|
296
305
|
return;
|
|
@@ -315,6 +324,11 @@ let FreeRideService = (() => {
|
|
|
315
324
|
done = true;
|
|
316
325
|
return;
|
|
317
326
|
}
|
|
327
|
+
if (lastHandlerWasNoOption) {
|
|
328
|
+
o.options = [];
|
|
329
|
+
done = true;
|
|
330
|
+
return;
|
|
331
|
+
}
|
|
318
332
|
try {
|
|
319
333
|
const map = segment.map ?? this.getMapArea().getMap(segment.path[0]);
|
|
320
334
|
const newPath = [];
|
|
@@ -343,13 +357,21 @@ let FreeRideService = (() => {
|
|
|
343
357
|
};
|
|
344
358
|
if (nextOpts?.length === 1) {
|
|
345
359
|
handleSingleOption();
|
|
360
|
+
lastHandlerWasNoOption = false;
|
|
346
361
|
}
|
|
347
|
-
else if (!nextOpts?.length) {
|
|
362
|
+
else if (!nextOpts?.length && isValid) {
|
|
348
363
|
handleNoOption();
|
|
364
|
+
lastHandlerWasNoOption = true;
|
|
365
|
+
}
|
|
366
|
+
else if (!nextOpts?.length && !isValid) {
|
|
367
|
+
o.options = [];
|
|
368
|
+
done = true;
|
|
369
|
+
lastHandlerWasNoOption = false;
|
|
349
370
|
}
|
|
350
371
|
else {
|
|
351
372
|
o.options = nextOpts;
|
|
352
373
|
done = true;
|
|
374
|
+
lastHandlerWasNoOption = false;
|
|
353
375
|
}
|
|
354
376
|
await (0, utils_2.waitNextTick)();
|
|
355
377
|
} while (!done);
|
|
@@ -364,6 +386,9 @@ let FreeRideService = (() => {
|
|
|
364
386
|
getOptions() {
|
|
365
387
|
return this.options;
|
|
366
388
|
}
|
|
389
|
+
isLastQueryValid() {
|
|
390
|
+
return this.lastOptionsQueryValid;
|
|
391
|
+
}
|
|
367
392
|
selectOption(option) {
|
|
368
393
|
const current = this.selectedOption;
|
|
369
394
|
const options = this.options ?? [];
|
|
@@ -22,15 +22,16 @@ export class OptionManager {
|
|
|
22
22
|
for (const segment of segments ?? []) {
|
|
23
23
|
try {
|
|
24
24
|
const path = segment.path;
|
|
25
|
-
const
|
|
25
|
+
const result = await this.getNextOptions(segment);
|
|
26
|
+
const opts = result.options;
|
|
26
27
|
if (opts?.length === 1) {
|
|
27
28
|
if (opts[0].id === segment.id) {
|
|
28
29
|
concatPaths(path, opts[0].path, 'after', opts[0].id);
|
|
29
30
|
}
|
|
30
31
|
else {
|
|
31
32
|
let foundSameSegment = false;
|
|
32
|
-
opts[0].path.forEach((point
|
|
33
|
-
if (
|
|
33
|
+
opts[0].path.forEach((point) => {
|
|
34
|
+
if (point === opts[0].path[0])
|
|
34
35
|
return;
|
|
35
36
|
foundSameSegment = points.some(pAll => pAll.id === point.id);
|
|
36
37
|
});
|
|
@@ -52,7 +53,7 @@ export class OptionManager {
|
|
|
52
53
|
async getNextOptions(from, props) {
|
|
53
54
|
try {
|
|
54
55
|
if (from?.id === undefined || from?.path === undefined || from?.path.length < 1) {
|
|
55
|
-
return [];
|
|
56
|
+
return { options: [], isValid: true };
|
|
56
57
|
}
|
|
57
58
|
const lastPoint = from.path.length > 0 ? from.path.at(-1) : undefined;
|
|
58
59
|
const fromWayId = lastPoint?.wayId ?? from.id;
|
|
@@ -62,7 +63,7 @@ export class OptionManager {
|
|
|
62
63
|
const query = { id: from.id, path: from.path, map: map };
|
|
63
64
|
originalWay = this.getWay(query);
|
|
64
65
|
if (!originalWay) {
|
|
65
|
-
return [];
|
|
66
|
+
return { options: [], isValid: true };
|
|
66
67
|
}
|
|
67
68
|
}
|
|
68
69
|
const way = { ...originalWay, path: from.path };
|
|
@@ -71,13 +72,13 @@ export class OptionManager {
|
|
|
71
72
|
if (way.path.length > 1)
|
|
72
73
|
location = way.path.at(-2);
|
|
73
74
|
else {
|
|
74
|
-
return [];
|
|
75
|
+
return { options: [], isValid: true };
|
|
75
76
|
}
|
|
76
77
|
}
|
|
77
78
|
const map = await this.service.load(location);
|
|
78
79
|
if (!map) {
|
|
79
80
|
if (!this.map?.isWithinBoundary(location))
|
|
80
|
-
return [];
|
|
81
|
+
return { options: [], isValid: true };
|
|
81
82
|
}
|
|
82
83
|
else {
|
|
83
84
|
this.setMap(map);
|
|
@@ -112,11 +113,11 @@ export class OptionManager {
|
|
|
112
113
|
const fromNode = from.path?.at(-2);
|
|
113
114
|
options = options.filter(o => o.path.length > 0 && o.path[1].id !== fromNode.id);
|
|
114
115
|
}
|
|
115
|
-
return options;
|
|
116
|
+
return { options, isValid: true };
|
|
116
117
|
}
|
|
117
118
|
catch (err) {
|
|
118
119
|
this.logError(err, 'getNextOptions');
|
|
119
|
-
return [];
|
|
120
|
+
return { options: [], isValid: false };
|
|
120
121
|
}
|
|
121
122
|
}
|
|
122
123
|
async checkMinDistance(options, minDistance) {
|
|
@@ -124,8 +125,8 @@ export class OptionManager {
|
|
|
124
125
|
if (option?.path?.length > 0) {
|
|
125
126
|
const distance = this.getDistance(option.path);
|
|
126
127
|
if (distance < minDistance) {
|
|
127
|
-
const
|
|
128
|
-
option.options =
|
|
128
|
+
const result = await this.getNextOptions(option, { minDistance: minDistance - distance });
|
|
129
|
+
option.options = result.options ?? [];
|
|
129
130
|
}
|
|
130
131
|
}
|
|
131
132
|
}
|
|
@@ -616,25 +616,30 @@ let RideDisplayService = (() => {
|
|
|
616
616
|
this.adjustCurrentStepDuration(time, newDuration);
|
|
617
617
|
this.updateActivityWorkout();
|
|
618
618
|
}
|
|
619
|
-
adjustPower(increase, large) {
|
|
619
|
+
adjustPower(increase, large, gearFallback = true) {
|
|
620
620
|
try {
|
|
621
621
|
if (this.getWorkoutRide().inUse()) {
|
|
622
622
|
const inc = large ? 5 : 1;
|
|
623
|
-
|
|
624
|
-
this.getWorkoutRide().powerUp(inc);
|
|
625
|
-
else
|
|
626
|
-
this.getWorkoutRide().powerDown(inc);
|
|
623
|
+
this.adjustWorkout(increase, inc);
|
|
627
624
|
}
|
|
628
625
|
else {
|
|
629
626
|
const sgn = increase ? 1 : -1;
|
|
630
627
|
const inc = large ? sgn * 50 : sgn * 5;
|
|
631
|
-
this.devicePowerUp(inc);
|
|
628
|
+
this.devicePowerUp(inc, gearFallback);
|
|
632
629
|
}
|
|
633
630
|
}
|
|
634
631
|
catch (err) {
|
|
635
632
|
this.logError(err, 'adjustPower');
|
|
636
633
|
}
|
|
637
634
|
}
|
|
635
|
+
adjustWorkout(increase, inc) {
|
|
636
|
+
if (this.getWorkoutRide().inUse()) {
|
|
637
|
+
if (increase)
|
|
638
|
+
this.getWorkoutRide().powerUp(inc);
|
|
639
|
+
else
|
|
640
|
+
this.getWorkoutRide().powerDown(inc);
|
|
641
|
+
}
|
|
642
|
+
}
|
|
638
643
|
adjustCurrentStepDuration(time, newDuration) {
|
|
639
644
|
let delta = 0;
|
|
640
645
|
this.actualWorkout?.steps?.forEach(s => {
|
|
@@ -842,7 +847,7 @@ let RideDisplayService = (() => {
|
|
|
842
847
|
devices.off('cycling-mode-toggle', h.toggleCyclingModeHandler);
|
|
843
848
|
delete this.startDeviceHandlers;
|
|
844
849
|
}
|
|
845
|
-
devicePowerUp(inc) {
|
|
850
|
+
devicePowerUp(inc, gearFallback = true) {
|
|
846
851
|
const device = this.getDeviceRide().getControlAdapter();
|
|
847
852
|
if (!device)
|
|
848
853
|
return;
|
|
@@ -858,9 +863,12 @@ let RideDisplayService = (() => {
|
|
|
858
863
|
if (Math.abs(gearDelta) > 1) {
|
|
859
864
|
gearDelta = Math.sign(gearDelta) * 5;
|
|
860
865
|
}
|
|
861
|
-
this.
|
|
866
|
+
this.gearChange(gearDelta);
|
|
862
867
|
}
|
|
863
868
|
}
|
|
869
|
+
gearChange(gearDelta) {
|
|
870
|
+
this.getRideModeService().sendUpdate({ gearDelta });
|
|
871
|
+
}
|
|
864
872
|
simulatorPowerUp(mode, powerInc) {
|
|
865
873
|
const simMode = mode.getSetting('mode');
|
|
866
874
|
let request = {};
|
|
@@ -982,6 +990,22 @@ let RideDisplayService = (() => {
|
|
|
982
990
|
this.adjustPower(true, duration > 1000);
|
|
983
991
|
else if (key === 'down')
|
|
984
992
|
this.adjustPower(false, duration > 1000);
|
|
993
|
+
else if (key == 'r-shift-up')
|
|
994
|
+
this.gearChange(1);
|
|
995
|
+
else if (key == 'r-shift-down')
|
|
996
|
+
this.gearChange(-1);
|
|
997
|
+
else if (key == 'l-shift-up')
|
|
998
|
+
this.gearChange(5);
|
|
999
|
+
else if (key == 'l-shift-down')
|
|
1000
|
+
this.gearChange(-5);
|
|
1001
|
+
else if (key == 'y')
|
|
1002
|
+
this.adjustPower(true, duration > 1000, false);
|
|
1003
|
+
else if (key == 'b')
|
|
1004
|
+
this.adjustPower(false, duration > 1000, false);
|
|
1005
|
+
else if (key == 'a')
|
|
1006
|
+
this.forward();
|
|
1007
|
+
else if (key == 'z')
|
|
1008
|
+
this.backward();
|
|
985
1009
|
}
|
|
986
1010
|
startListeningForDeviceData() {
|
|
987
1011
|
const { deviceDataHandler } = this.startDeviceHandlers ?? {};
|
|
@@ -289,7 +289,8 @@ let RidePageService = (() => {
|
|
|
289
289
|
startOverlayProps: isStarting ? this.getRideDisplay().getStartOverlayProps() : null,
|
|
290
290
|
menuProps: this.menuProps,
|
|
291
291
|
rideView: props.rideView,
|
|
292
|
-
route: props.route
|
|
292
|
+
route: props.route,
|
|
293
|
+
displayObserver: props.displayObserver
|
|
293
294
|
};
|
|
294
295
|
return displayProps;
|
|
295
296
|
}
|
|
@@ -416,11 +416,11 @@ let FreeRideDisplayService = (() => {
|
|
|
416
416
|
this.logError(err, 'getNextOptions');
|
|
417
417
|
options = undefined;
|
|
418
418
|
}
|
|
419
|
-
if (!options?.length && !finished && !forStart) {
|
|
419
|
+
if (!options?.length && !finished && !forStart && !freeRide.isLastQueryValid()) {
|
|
420
420
|
this.logEvent({ message: 'no options available - retry in 3000ms', });
|
|
421
421
|
await sleep(3000);
|
|
422
422
|
}
|
|
423
|
-
} while (!options?.length && !finished && !forStart);
|
|
423
|
+
} while (!options?.length && !finished && !forStart && !freeRide.isLastQueryValid());
|
|
424
424
|
this.internalEmitter.off('stop-query', setFinished);
|
|
425
425
|
};
|
|
426
426
|
return new Promise(done => {
|
|
@@ -100,6 +100,8 @@ let GpxDisplayService = (() => {
|
|
|
100
100
|
displayPosition: this.mapLoaded ? null : this.position,
|
|
101
101
|
sideViews
|
|
102
102
|
};
|
|
103
|
+
if (this.isMobile()) {
|
|
104
|
+
}
|
|
103
105
|
return props;
|
|
104
106
|
}
|
|
105
107
|
getSatelliteViewProps() {
|
|
@@ -117,7 +119,7 @@ let GpxDisplayService = (() => {
|
|
|
117
119
|
}
|
|
118
120
|
getStartOverlayProps() {
|
|
119
121
|
const rideView = this.getRideView();
|
|
120
|
-
if (rideView === 'map') {
|
|
122
|
+
if (rideView === 'map' || this.isMobile()) {
|
|
121
123
|
return {
|
|
122
124
|
mapType: this.getRideViewName(),
|
|
123
125
|
mapState: 'Loaded'
|
|
@@ -131,7 +133,7 @@ let GpxDisplayService = (() => {
|
|
|
131
133
|
}
|
|
132
134
|
isStartRideCompleted() {
|
|
133
135
|
const rideView = this.getRideView();
|
|
134
|
-
if (rideView === 'map') {
|
|
136
|
+
if (rideView === 'map' || this.isMobile()) {
|
|
135
137
|
this.mapLoaded = true;
|
|
136
138
|
return true;
|
|
137
139
|
}
|
|
@@ -156,7 +158,7 @@ let GpxDisplayService = (() => {
|
|
|
156
158
|
}
|
|
157
159
|
getRideView() {
|
|
158
160
|
if (this.isMobile())
|
|
159
|
-
return '
|
|
161
|
+
return 'sv';
|
|
160
162
|
const rideView = this.getUserSettings().get('preferences.rideView', 'sv');
|
|
161
163
|
return rideView;
|
|
162
164
|
}
|
|
@@ -69,6 +69,7 @@ let FreeRideService = (() => {
|
|
|
69
69
|
selectedOption;
|
|
70
70
|
options;
|
|
71
71
|
currentSegment;
|
|
72
|
+
lastOptionsQueryValid = true;
|
|
72
73
|
constructor() {
|
|
73
74
|
super('FreeRide');
|
|
74
75
|
this.options = [];
|
|
@@ -131,7 +132,12 @@ let FreeRideService = (() => {
|
|
|
131
132
|
}
|
|
132
133
|
async loadNextOptions(from, forStart) {
|
|
133
134
|
const optionManager = useMapArea().getOptionManager();
|
|
134
|
-
|
|
135
|
+
const result = await optionManager.getNextOptions(from);
|
|
136
|
+
let opts = result.options;
|
|
137
|
+
this.lastOptionsQueryValid = result.isValid;
|
|
138
|
+
if (!result.isValid) {
|
|
139
|
+
return [];
|
|
140
|
+
}
|
|
135
141
|
opts = this.evaluateOptions(opts, from);
|
|
136
142
|
if (forStart)
|
|
137
143
|
await this.getNextLevelOptions(opts);
|
|
@@ -283,8 +289,11 @@ let FreeRideService = (() => {
|
|
|
283
289
|
let segment = o;
|
|
284
290
|
let done = false;
|
|
285
291
|
let isSingle = false;
|
|
292
|
+
let lastHandlerWasNoOption = false;
|
|
286
293
|
do {
|
|
287
|
-
const
|
|
294
|
+
const nextOptsResult = await optionManager.getNextOptions(segment);
|
|
295
|
+
const nextOpts = nextOptsResult.options;
|
|
296
|
+
const isValid = nextOptsResult.isValid;
|
|
288
297
|
const handleSingleOption = () => {
|
|
289
298
|
if (segmentUpdated)
|
|
290
299
|
return;
|
|
@@ -309,6 +318,11 @@ let FreeRideService = (() => {
|
|
|
309
318
|
done = true;
|
|
310
319
|
return;
|
|
311
320
|
}
|
|
321
|
+
if (lastHandlerWasNoOption) {
|
|
322
|
+
o.options = [];
|
|
323
|
+
done = true;
|
|
324
|
+
return;
|
|
325
|
+
}
|
|
312
326
|
try {
|
|
313
327
|
const map = segment.map ?? this.getMapArea().getMap(segment.path[0]);
|
|
314
328
|
const newPath = [];
|
|
@@ -337,13 +351,21 @@ let FreeRideService = (() => {
|
|
|
337
351
|
};
|
|
338
352
|
if (nextOpts?.length === 1) {
|
|
339
353
|
handleSingleOption();
|
|
354
|
+
lastHandlerWasNoOption = false;
|
|
340
355
|
}
|
|
341
|
-
else if (!nextOpts?.length) {
|
|
356
|
+
else if (!nextOpts?.length && isValid) {
|
|
342
357
|
handleNoOption();
|
|
358
|
+
lastHandlerWasNoOption = true;
|
|
359
|
+
}
|
|
360
|
+
else if (!nextOpts?.length && !isValid) {
|
|
361
|
+
o.options = [];
|
|
362
|
+
done = true;
|
|
363
|
+
lastHandlerWasNoOption = false;
|
|
343
364
|
}
|
|
344
365
|
else {
|
|
345
366
|
o.options = nextOpts;
|
|
346
367
|
done = true;
|
|
368
|
+
lastHandlerWasNoOption = false;
|
|
347
369
|
}
|
|
348
370
|
await waitNextTick();
|
|
349
371
|
} while (!done);
|
|
@@ -358,6 +380,9 @@ let FreeRideService = (() => {
|
|
|
358
380
|
getOptions() {
|
|
359
381
|
return this.options;
|
|
360
382
|
}
|
|
383
|
+
isLastQueryValid() {
|
|
384
|
+
return this.lastOptionsQueryValid;
|
|
385
|
+
}
|
|
361
386
|
selectOption(option) {
|
|
362
387
|
const current = this.selectedOption;
|
|
363
388
|
const options = this.options ?? [];
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { EventLogger } from "gd-eventlog";
|
|
2
|
-
import { FreeRideContinuation, GetNextOptionProps, IMapArea, IMapAreaService, IncyclistNode, IncyclistWay, PathCrossingInfo, WayInfo } from "./types";
|
|
2
|
+
import { FreeRideContinuation, GetNextOptionProps, IMapArea, IMapAreaService, IncyclistNode, IncyclistWay, NextOptionsResult, PathCrossingInfo, WayInfo } from "./types";
|
|
3
3
|
export declare class OptionManager {
|
|
4
4
|
protected service: IMapAreaService;
|
|
5
5
|
protected map?: IMapArea;
|
|
@@ -7,7 +7,7 @@ export declare class OptionManager {
|
|
|
7
7
|
constructor(service: IMapAreaService, map?: IMapArea);
|
|
8
8
|
setMap(map: IMapArea): void;
|
|
9
9
|
getStartOptions(way: IncyclistWay, crossing: PathCrossingInfo): Promise<Array<FreeRideContinuation>>;
|
|
10
|
-
getNextOptions(from: WayInfo | FreeRideContinuation, props?: GetNextOptionProps): Promise<
|
|
10
|
+
getNextOptions(from: WayInfo | FreeRideContinuation, props?: GetNextOptionProps): Promise<NextOptionsResult>;
|
|
11
11
|
protected checkMinDistance(options: Array<FreeRideContinuation>, minDistance: number): Promise<void>;
|
|
12
12
|
protected getDistance(path: IncyclistNode[]): number;
|
|
13
13
|
protected checkOptionsOnDifferentWay(location: IncyclistNode, w: IncyclistWay, options: FreeRideContinuation[]): FreeRideContinuation[];
|
|
@@ -37,6 +37,10 @@ export type FreeRideContinuation = {
|
|
|
37
37
|
map?: IMapArea;
|
|
38
38
|
ui?: FreeRideOption;
|
|
39
39
|
};
|
|
40
|
+
export type NextOptionsResult = {
|
|
41
|
+
options: Array<FreeRideContinuation>;
|
|
42
|
+
isValid: boolean;
|
|
43
|
+
};
|
|
40
44
|
export interface IMapAreaService {
|
|
41
45
|
load(location: IncyclistNode): Promise<IMapArea | undefined>;
|
|
42
46
|
getMap(location: IncyclistNode): IMapArea | undefined;
|
|
@@ -11,6 +11,7 @@ import { FreeRideOption } from "../../routes/list/types";
|
|
|
11
11
|
import { MapViewPort } from "../route/types";
|
|
12
12
|
import { LatLng } from "../../utils/geo";
|
|
13
13
|
import { Unit } from "../../i18n";
|
|
14
|
+
import { IObserver } from "../../types";
|
|
14
15
|
export type RideType = 'Free-Ride' | 'GPX' | 'Video' | 'Workout';
|
|
15
16
|
export type CurrentRideState = 'Idle' | 'Starting' | 'Started' | 'Active' | 'Paused' | 'Error' | 'Finished' | 'Closing';
|
|
16
17
|
export type CurrentRideDeviceState = 'Starting' | 'Started' | 'Error';
|
|
@@ -102,6 +103,7 @@ export interface MapOverlayDisplayProps extends OverlayDisplayProps {
|
|
|
102
103
|
export type RideViewType = 'sv' | 'map' | 'sat';
|
|
103
104
|
export interface GpxDisplayProps extends RouteDisplayProps {
|
|
104
105
|
rideView: RideViewType;
|
|
106
|
+
displayObserver?: IObserver;
|
|
105
107
|
}
|
|
106
108
|
export interface RouteOptionDisplayProps {
|
|
107
109
|
optionsDelay?: number;
|
|
@@ -78,7 +78,8 @@ export declare class RideDisplayService extends IncyclistService implements ICur
|
|
|
78
78
|
onRouteUpdated(route: Route): void;
|
|
79
79
|
protected onRouteCompleted(): void;
|
|
80
80
|
protected onForward(workoutTime: number, remaining: number): void;
|
|
81
|
-
adjustPower(increase: boolean, large: boolean): void;
|
|
81
|
+
adjustPower(increase: boolean, large: boolean, gearFallback?: boolean): void;
|
|
82
|
+
adjustWorkout(increase: boolean, inc: number): void;
|
|
82
83
|
protected adjustCurrentStepDuration(time: number, newDuration: number): void;
|
|
83
84
|
protected onBackward(workoutTime: number, duration: number, jumpType: 'current' | 'previous', jumpFrom: Step, jumpTo: Step): void;
|
|
84
85
|
protected adjustStepDuration(s: Step, newDuration: any): void;
|
|
@@ -95,7 +96,8 @@ export declare class RideDisplayService extends IncyclistService implements ICur
|
|
|
95
96
|
protected stopDevices(exit?: boolean): void;
|
|
96
97
|
protected initDeviceHandlers(): void;
|
|
97
98
|
protected resetDeviceHandlers(): void;
|
|
98
|
-
protected devicePowerUp(inc: number): void;
|
|
99
|
+
protected devicePowerUp(inc: number, gearFallback?: boolean): void;
|
|
100
|
+
protected gearChange(gearDelta: number): void;
|
|
99
101
|
protected simulatorPowerUp(mode: CyclingMode, powerInc: number): void;
|
|
100
102
|
protected onDeviceStartRequest(devices: AdapterStateInfo[]): void;
|
|
101
103
|
protected updateStartOverlay(): void;
|
|
@@ -20,6 +20,7 @@ export interface VideoRidePageDisplayProps extends RidePageDisplayProps {
|
|
|
20
20
|
}
|
|
21
21
|
export interface GPXRidePageDisplayProps extends RidePageDisplayProps {
|
|
22
22
|
rideView?: RideViewType;
|
|
23
|
+
displayObserver?: IObserver;
|
|
23
24
|
}
|
|
24
25
|
export type AnyRidePageDisplayProps = VideoRidePageDisplayProps | RidePageDisplayProps;
|
|
25
26
|
export interface RideMenuProps {
|
|
@@ -8,6 +8,7 @@ export declare class FreeRideService extends IncyclistService {
|
|
|
8
8
|
protected selectedOption: FreeRideContinuation;
|
|
9
9
|
protected options: FreeRideContinuation[];
|
|
10
10
|
protected currentSegment: FreeRideContinuation;
|
|
11
|
+
protected lastOptionsQueryValid: boolean;
|
|
11
12
|
constructor();
|
|
12
13
|
selectStartPosition(position?: LatLng | undefined): Promise<{
|
|
13
14
|
position: IncyclistNode;
|
|
@@ -34,6 +35,7 @@ export declare class FreeRideService extends IncyclistService {
|
|
|
34
35
|
protected getNextLevelOptions(opts: FreeRideContinuation[]): Promise<void>;
|
|
35
36
|
protected buildId(opt: FreeRideContinuation): string;
|
|
36
37
|
getOptions(): FreeRideContinuation[];
|
|
38
|
+
isLastQueryValid(): boolean;
|
|
37
39
|
selectOption(option: FreeRideContinuation | string | number): FreeRideContinuation[];
|
|
38
40
|
applyOption(option?: FreeRideContinuation): void;
|
|
39
41
|
applyStartOption(startOption?: FreeRideOption): void;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-services",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.60",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"gd-eventlog": "^0.1.27"
|
|
6
6
|
},
|
|
7
7
|
"dependencies": {
|
|
8
8
|
"@garmin/fitsdk": "^21.200.0",
|
|
9
9
|
"axios": "^1.15.2",
|
|
10
|
-
"incyclist-devices": "^3.0.
|
|
10
|
+
"incyclist-devices": "^3.0.16",
|
|
11
11
|
"promise.any": "^2.0.6",
|
|
12
12
|
"semver": "^7.7.4",
|
|
13
13
|
"tcx-builder": "^1.1.1",
|