incyclist-services 1.7.85 → 1.7.87
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/devices/configuration/service.js +25 -2
- package/lib/cjs/devices/pairing/service.js +11 -11
- package/lib/cjs/maps/MapArea/utils.js +4 -2
- package/lib/cjs/workouts/base/graph/series.js +2 -2
- package/lib/cjs/workouts/ride/page/service.js +13 -6
- package/lib/cjs/workouts/ride/service.js +10 -2
- package/lib/esm/devices/configuration/service.js +25 -2
- package/lib/esm/devices/pairing/service.js +11 -11
- package/lib/esm/maps/MapArea/utils.js +4 -2
- package/lib/esm/workouts/base/graph/series.js +2 -2
- package/lib/esm/workouts/ride/page/service.js +13 -6
- package/lib/esm/workouts/ride/service.js +10 -2
- package/lib/types/devices/configuration/service.d.ts +2 -0
- package/lib/types/devices/pairing/model.d.ts +2 -1
- package/lib/types/devices/pairing/service.d.ts +1 -2
- package/lib/types/workouts/base/graph/series.d.ts +1 -4
- package/lib/types/workouts/ride/page/service.d.ts +3 -2
- package/lib/types/workouts/ride/service.d.ts +3 -3
- package/lib/types/workouts/ride/types.d.ts +4 -0
- package/package.json +4 -3
|
@@ -235,13 +235,18 @@ let DeviceConfigurationService = (() => {
|
|
|
235
235
|
}
|
|
236
236
|
add(deviceSettings, props) {
|
|
237
237
|
let udid = this.getUdid(deviceSettings);
|
|
238
|
+
udid ??= this.getUdidForWifiAddressChange(deviceSettings);
|
|
238
239
|
const { legacy = false } = props || {};
|
|
239
240
|
const deviceAlreadyExists = udid !== undefined;
|
|
240
241
|
let adapter;
|
|
241
242
|
const updateWifiSettings = (udid) => {
|
|
242
243
|
const settingIdx = this.settings.devices.findIndex(d => d.udid === udid);
|
|
243
244
|
if (settingIdx !== -1 && this.settings.devices[settingIdx]?.settings?.interface === 'wifi') {
|
|
244
|
-
|
|
245
|
+
const merged = { ...this.settings.devices[settingIdx].settings, ...deviceSettings };
|
|
246
|
+
this.settings.devices[settingIdx].settings = merged;
|
|
247
|
+
if (this.adapters[udid]) {
|
|
248
|
+
this.adapters[udid].settings = merged;
|
|
249
|
+
}
|
|
245
250
|
}
|
|
246
251
|
};
|
|
247
252
|
if (deviceAlreadyExists && this.adapters[udid]) {
|
|
@@ -255,7 +260,7 @@ let DeviceConfigurationService = (() => {
|
|
|
255
260
|
this.logEvent({ message: 'could not create adapter' });
|
|
256
261
|
return;
|
|
257
262
|
}
|
|
258
|
-
udid = this.settings.devices?.find(d => adapter.isEqual(d.settings))?.udid;
|
|
263
|
+
udid = this.settings.devices?.find(d => adapter.isEqual(d.settings))?.udid ?? this.getUdidForWifiAddressChange(deviceSettings);
|
|
259
264
|
if (udid) {
|
|
260
265
|
updateWifiSettings(udid);
|
|
261
266
|
}
|
|
@@ -338,6 +343,24 @@ let DeviceConfigurationService = (() => {
|
|
|
338
343
|
const udid = udids.find(key => this.adapters[key]?.isEqual(deviceSettings));
|
|
339
344
|
return udid;
|
|
340
345
|
}
|
|
346
|
+
getUdidForWifiAddressChange(deviceSettings) {
|
|
347
|
+
const settings = deviceSettings;
|
|
348
|
+
if (settings?.interface !== 'wifi' || !settings.name)
|
|
349
|
+
return undefined;
|
|
350
|
+
const dc = this.getDirectConnectInterface();
|
|
351
|
+
if (typeof dc?.hasNameCollision === 'function' && dc.hasNameCollision(settings.name))
|
|
352
|
+
return undefined;
|
|
353
|
+
return this.settings.devices?.find(d => {
|
|
354
|
+
const s = d.settings;
|
|
355
|
+
return s?.interface === 'wifi' && s.name === settings.name;
|
|
356
|
+
})?.udid;
|
|
357
|
+
}
|
|
358
|
+
isEqualDeviceSettings(a, b) {
|
|
359
|
+
if (!a || !b)
|
|
360
|
+
return false;
|
|
361
|
+
const adapter = this.getAdapterFromSetting(a);
|
|
362
|
+
return adapter?.isEqual(b) ?? false;
|
|
363
|
+
}
|
|
341
364
|
setDisplayName(deviceSettings, displayName) {
|
|
342
365
|
const udid = this.getUdid(deviceSettings);
|
|
343
366
|
if (!udid)
|
|
@@ -832,6 +832,12 @@ let DevicePairingService = (() => {
|
|
|
832
832
|
this.logEvent({ message: 'device could not be added', reason: 'add() failed' });
|
|
833
833
|
return;
|
|
834
834
|
}
|
|
835
|
+
const deletedCapabilities = (this.state.deleted || [])
|
|
836
|
+
.filter(e => e.udid === udid || (e.settings && this.getDeviceConfiguration().isEqualDeviceSettings(e.settings, deviceSettings)))
|
|
837
|
+
.map(e => e.capability);
|
|
838
|
+
deletedCapabilities.forEach(capability => {
|
|
839
|
+
this.getDeviceConfiguration().delete(udid, capability, true);
|
|
840
|
+
});
|
|
835
841
|
const adapter = this.getDeviceConfiguration().getAdapter(udid);
|
|
836
842
|
if (adapter) {
|
|
837
843
|
adapter.onScanStart();
|
|
@@ -1411,8 +1417,9 @@ let DevicePairingService = (() => {
|
|
|
1411
1417
|
c.value = undefined;
|
|
1412
1418
|
c.connectState = undefined;
|
|
1413
1419
|
}
|
|
1414
|
-
this.
|
|
1415
|
-
this.
|
|
1420
|
+
const settings = this.getDeviceAdapter(udid)?.getSettings?.();
|
|
1421
|
+
this.getDeviceConfiguration().delete(udid, capability, true);
|
|
1422
|
+
this.addToDeletedList(capability, udid, settings);
|
|
1416
1423
|
this.emitStateChange({ capabilities: this.state.capabilities });
|
|
1417
1424
|
}
|
|
1418
1425
|
isScanning() {
|
|
@@ -1440,18 +1447,11 @@ let DevicePairingService = (() => {
|
|
|
1440
1447
|
numberOfSelectedCababilities(udid) {
|
|
1441
1448
|
return (this.state.capabilities || []).map(c => c.selected === udid ? 1 : 0).reduce((a, c) => a + c, 0);
|
|
1442
1449
|
}
|
|
1443
|
-
addToDeletedList(capability, udid) {
|
|
1450
|
+
addToDeletedList(capability, udid, settings) {
|
|
1444
1451
|
if (this.isOnDeletedList(capability, udid))
|
|
1445
1452
|
return;
|
|
1446
1453
|
const c = this.getCapability(capability);
|
|
1447
|
-
this.state.deleted.push({ capability: c.capability, udid });
|
|
1448
|
-
}
|
|
1449
|
-
removeFromDeletedList(capability, udid) {
|
|
1450
|
-
const c = this.getCapability(capability);
|
|
1451
|
-
const idx = this.state.deleted.findIndex(e => e.capability === c.capability && e.udid === udid);
|
|
1452
|
-
if (idx === -1)
|
|
1453
|
-
return;
|
|
1454
|
-
this.state.deleted.splice(idx, 1);
|
|
1454
|
+
this.state.deleted.push({ capability: c.capability, udid, settings });
|
|
1455
1455
|
}
|
|
1456
1456
|
isOnDeletedList(c, udid) {
|
|
1457
1457
|
const capability = this.getCapability(c);
|
|
@@ -134,11 +134,13 @@ function concatPaths(path, path2, position, wayId) {
|
|
|
134
134
|
}
|
|
135
135
|
if (position === 'after') {
|
|
136
136
|
append.shift();
|
|
137
|
-
path.push(
|
|
137
|
+
append.forEach(p => path.push(p));
|
|
138
138
|
}
|
|
139
139
|
else {
|
|
140
140
|
path.shift();
|
|
141
|
-
|
|
141
|
+
const newPath = append.concat(path);
|
|
142
|
+
path.length = 0;
|
|
143
|
+
newPath.forEach(p => path.push(p));
|
|
142
144
|
}
|
|
143
145
|
}
|
|
144
146
|
function splitAtPointInfo(way, split) {
|
|
@@ -115,8 +115,8 @@ function formatRange(low, high, unit, rangePrefix = '') {
|
|
|
115
115
|
const v = high ?? low;
|
|
116
116
|
return v === undefined ? '' : `${Math.round(v)}${unit}`;
|
|
117
117
|
}
|
|
118
|
-
function getStepTargetText(step, ftp
|
|
119
|
-
const { min: minPower, max: maxPower } =
|
|
118
|
+
function getStepTargetText(step, ftp) {
|
|
119
|
+
const { min: minPower, max: maxPower } = resolvePowerWatts(step.power, ftp);
|
|
120
120
|
const ascending = step.steady || step.cooldown === false;
|
|
121
121
|
const lowPower = ascending ? minPower : maxPower;
|
|
122
122
|
const highPower = ascending ? maxPower : minPower;
|
|
@@ -167,7 +167,7 @@ let WorkoutRidePageService = (() => {
|
|
|
167
167
|
const current = this.getRideDisplay().getDisplayProperties().workout;
|
|
168
168
|
return {
|
|
169
169
|
...base,
|
|
170
|
-
title: wo
|
|
170
|
+
title: this.getMobileStepTitle(wo),
|
|
171
171
|
graph: this.buildGraphPlan(current, wo.ftp),
|
|
172
172
|
steps: this.buildUpcomingSteps(current, wo.ftp),
|
|
173
173
|
dashboard: this.buildDashboardLine(wo),
|
|
@@ -326,12 +326,13 @@ let WorkoutRidePageService = (() => {
|
|
|
326
326
|
adjustLoad(deltaPct) {
|
|
327
327
|
try {
|
|
328
328
|
if (deltaPct >= 0)
|
|
329
|
-
this.getWorkoutRide().powerUp(deltaPct);
|
|
329
|
+
return this.getWorkoutRide().powerUp(deltaPct);
|
|
330
330
|
else
|
|
331
|
-
this.getWorkoutRide().powerDown(-deltaPct);
|
|
331
|
+
return this.getWorkoutRide().powerDown(-deltaPct);
|
|
332
332
|
}
|
|
333
333
|
catch (err) {
|
|
334
334
|
this.logError(err, 'adjustLoad');
|
|
335
|
+
return undefined;
|
|
335
336
|
}
|
|
336
337
|
}
|
|
337
338
|
onRideStateUpdate(state) {
|
|
@@ -427,7 +428,7 @@ let WorkoutRidePageService = (() => {
|
|
|
427
428
|
if (!limits)
|
|
428
429
|
return empty;
|
|
429
430
|
const currentStep = {
|
|
430
|
-
label: (0, graph_1.getStepTargetText)(limits.step ?? {}, ftp
|
|
431
|
+
label: (0, graph_1.getStepTargetText)(limits.step ?? {}, ftp),
|
|
431
432
|
targetPower: limits.targetPower ?? null,
|
|
432
433
|
duration: limits.duration,
|
|
433
434
|
remaining: limits.remaining,
|
|
@@ -451,12 +452,18 @@ let WorkoutRidePageService = (() => {
|
|
|
451
452
|
const hasMore = currentIndex + 1 + UPCOMING_STEPS_COUNT < flattened.length;
|
|
452
453
|
return { previous, current: currentStep, upcoming, hasMore };
|
|
453
454
|
}
|
|
455
|
+
getMobileStepTitle(wo) {
|
|
456
|
+
const title = wo.title ?? '';
|
|
457
|
+
const name = wo.workout?.name;
|
|
458
|
+
const prefix = name ? `${name}: ` : '';
|
|
459
|
+
return prefix && title.startsWith(prefix) ? title.slice(prefix.length) : title;
|
|
460
|
+
}
|
|
454
461
|
buildDashboardLine(wo) {
|
|
455
462
|
const limits = this.getWorkoutRide().getCurrentLimits();
|
|
456
|
-
const title = wo
|
|
463
|
+
const title = this.getMobileStepTitle(wo);
|
|
457
464
|
if (!limits)
|
|
458
465
|
return { text: title, mode: wo.mode ?? null };
|
|
459
|
-
const target = (0, graph_1.getStepTargetText)(limits.step ?? {}, wo.ftp
|
|
466
|
+
const target = (0, graph_1.getStepTargetText)(limits.step ?? {}, wo.ftp);
|
|
460
467
|
const duration = (0, graph_1.getStepDuration)({ duration: limits.duration });
|
|
461
468
|
const text = title ? `${target} for ${duration} - ${title}` : `${target} for ${duration}`;
|
|
462
469
|
return { text, mode: wo.mode ?? null };
|
|
@@ -280,19 +280,23 @@ let WorkoutRide = (() => {
|
|
|
280
280
|
this.currentLimits.targetPower = Math.min(this.currentLimits.targetPower + deltaVal, this.currentLimits.maxPower);
|
|
281
281
|
this.logEvent({ message: 'workout target power adjusted', targetPower: this.currentLimits.targetPower });
|
|
282
282
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
283
|
-
return;
|
|
283
|
+
return { type: 'targetPower', value: this.currentLimits.targetPower };
|
|
284
284
|
}
|
|
285
|
+
let adjustedFtp;
|
|
285
286
|
if (this.settings?.ftp) {
|
|
286
287
|
this.settings.ftp = this.settings.ftp * (1 + delta / 100);
|
|
287
288
|
this.workoutList.setStartSettings(this.settings);
|
|
288
289
|
this.logEvent({ message: 'workout FTP adjusted', ftp: this.settings.ftp });
|
|
290
|
+
adjustedFtp = Math.round(this.settings.ftp);
|
|
289
291
|
}
|
|
290
292
|
this.manualPowerOffset += delta;
|
|
291
293
|
this.setCurrentLimits();
|
|
292
294
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
295
|
+
return adjustedFtp !== undefined ? { type: 'ftp', value: adjustedFtp } : undefined;
|
|
293
296
|
}
|
|
294
297
|
catch (err) {
|
|
295
298
|
this.logError(err, 'powerUp');
|
|
299
|
+
return undefined;
|
|
296
300
|
}
|
|
297
301
|
}
|
|
298
302
|
powerDown(delta) {
|
|
@@ -306,19 +310,23 @@ let WorkoutRide = (() => {
|
|
|
306
310
|
this.currentLimits.targetPower = Math.max(this.currentLimits.targetPower - deltaVal, this.currentLimits.minPower);
|
|
307
311
|
this.logEvent({ message: 'workout target power adjusted', targetPower: this.currentLimits.targetPower });
|
|
308
312
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
309
|
-
return;
|
|
313
|
+
return { type: 'targetPower', value: this.currentLimits.targetPower };
|
|
310
314
|
}
|
|
315
|
+
let adjustedFtp;
|
|
311
316
|
if (this.settings?.ftp) {
|
|
312
317
|
this.settings.ftp = this.settings.ftp / (1 + delta / 100);
|
|
313
318
|
this.workoutList.setStartSettings(this.settings);
|
|
314
319
|
this.logEvent({ message: 'workout FTP adjusted', ftp: this.settings.ftp });
|
|
320
|
+
adjustedFtp = Math.round(this.settings.ftp);
|
|
315
321
|
}
|
|
316
322
|
this.manualPowerOffset -= delta;
|
|
317
323
|
this.setCurrentLimits();
|
|
318
324
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
325
|
+
return adjustedFtp !== undefined ? { type: 'ftp', value: adjustedFtp } : undefined;
|
|
319
326
|
}
|
|
320
327
|
catch (err) {
|
|
321
328
|
this.logError(err, 'powerDown');
|
|
329
|
+
return undefined;
|
|
322
330
|
}
|
|
323
331
|
}
|
|
324
332
|
toggleCyclingMode() {
|
|
@@ -229,13 +229,18 @@ let DeviceConfigurationService = (() => {
|
|
|
229
229
|
}
|
|
230
230
|
add(deviceSettings, props) {
|
|
231
231
|
let udid = this.getUdid(deviceSettings);
|
|
232
|
+
udid ??= this.getUdidForWifiAddressChange(deviceSettings);
|
|
232
233
|
const { legacy = false } = props || {};
|
|
233
234
|
const deviceAlreadyExists = udid !== undefined;
|
|
234
235
|
let adapter;
|
|
235
236
|
const updateWifiSettings = (udid) => {
|
|
236
237
|
const settingIdx = this.settings.devices.findIndex(d => d.udid === udid);
|
|
237
238
|
if (settingIdx !== -1 && this.settings.devices[settingIdx]?.settings?.interface === 'wifi') {
|
|
238
|
-
|
|
239
|
+
const merged = { ...this.settings.devices[settingIdx].settings, ...deviceSettings };
|
|
240
|
+
this.settings.devices[settingIdx].settings = merged;
|
|
241
|
+
if (this.adapters[udid]) {
|
|
242
|
+
this.adapters[udid].settings = merged;
|
|
243
|
+
}
|
|
239
244
|
}
|
|
240
245
|
};
|
|
241
246
|
if (deviceAlreadyExists && this.adapters[udid]) {
|
|
@@ -249,7 +254,7 @@ let DeviceConfigurationService = (() => {
|
|
|
249
254
|
this.logEvent({ message: 'could not create adapter' });
|
|
250
255
|
return;
|
|
251
256
|
}
|
|
252
|
-
udid = this.settings.devices?.find(d => adapter.isEqual(d.settings))?.udid;
|
|
257
|
+
udid = this.settings.devices?.find(d => adapter.isEqual(d.settings))?.udid ?? this.getUdidForWifiAddressChange(deviceSettings);
|
|
253
258
|
if (udid) {
|
|
254
259
|
updateWifiSettings(udid);
|
|
255
260
|
}
|
|
@@ -332,6 +337,24 @@ let DeviceConfigurationService = (() => {
|
|
|
332
337
|
const udid = udids.find(key => this.adapters[key]?.isEqual(deviceSettings));
|
|
333
338
|
return udid;
|
|
334
339
|
}
|
|
340
|
+
getUdidForWifiAddressChange(deviceSettings) {
|
|
341
|
+
const settings = deviceSettings;
|
|
342
|
+
if (settings?.interface !== 'wifi' || !settings.name)
|
|
343
|
+
return undefined;
|
|
344
|
+
const dc = this.getDirectConnectInterface();
|
|
345
|
+
if (typeof dc?.hasNameCollision === 'function' && dc.hasNameCollision(settings.name))
|
|
346
|
+
return undefined;
|
|
347
|
+
return this.settings.devices?.find(d => {
|
|
348
|
+
const s = d.settings;
|
|
349
|
+
return s?.interface === 'wifi' && s.name === settings.name;
|
|
350
|
+
})?.udid;
|
|
351
|
+
}
|
|
352
|
+
isEqualDeviceSettings(a, b) {
|
|
353
|
+
if (!a || !b)
|
|
354
|
+
return false;
|
|
355
|
+
const adapter = this.getAdapterFromSetting(a);
|
|
356
|
+
return adapter?.isEqual(b) ?? false;
|
|
357
|
+
}
|
|
335
358
|
setDisplayName(deviceSettings, displayName) {
|
|
336
359
|
const udid = this.getUdid(deviceSettings);
|
|
337
360
|
if (!udid)
|
|
@@ -826,6 +826,12 @@ let DevicePairingService = (() => {
|
|
|
826
826
|
this.logEvent({ message: 'device could not be added', reason: 'add() failed' });
|
|
827
827
|
return;
|
|
828
828
|
}
|
|
829
|
+
const deletedCapabilities = (this.state.deleted || [])
|
|
830
|
+
.filter(e => e.udid === udid || (e.settings && this.getDeviceConfiguration().isEqualDeviceSettings(e.settings, deviceSettings)))
|
|
831
|
+
.map(e => e.capability);
|
|
832
|
+
deletedCapabilities.forEach(capability => {
|
|
833
|
+
this.getDeviceConfiguration().delete(udid, capability, true);
|
|
834
|
+
});
|
|
829
835
|
const adapter = this.getDeviceConfiguration().getAdapter(udid);
|
|
830
836
|
if (adapter) {
|
|
831
837
|
adapter.onScanStart();
|
|
@@ -1405,8 +1411,9 @@ let DevicePairingService = (() => {
|
|
|
1405
1411
|
c.value = undefined;
|
|
1406
1412
|
c.connectState = undefined;
|
|
1407
1413
|
}
|
|
1408
|
-
this.
|
|
1409
|
-
this.
|
|
1414
|
+
const settings = this.getDeviceAdapter(udid)?.getSettings?.();
|
|
1415
|
+
this.getDeviceConfiguration().delete(udid, capability, true);
|
|
1416
|
+
this.addToDeletedList(capability, udid, settings);
|
|
1410
1417
|
this.emitStateChange({ capabilities: this.state.capabilities });
|
|
1411
1418
|
}
|
|
1412
1419
|
isScanning() {
|
|
@@ -1434,18 +1441,11 @@ let DevicePairingService = (() => {
|
|
|
1434
1441
|
numberOfSelectedCababilities(udid) {
|
|
1435
1442
|
return (this.state.capabilities || []).map(c => c.selected === udid ? 1 : 0).reduce((a, c) => a + c, 0);
|
|
1436
1443
|
}
|
|
1437
|
-
addToDeletedList(capability, udid) {
|
|
1444
|
+
addToDeletedList(capability, udid, settings) {
|
|
1438
1445
|
if (this.isOnDeletedList(capability, udid))
|
|
1439
1446
|
return;
|
|
1440
1447
|
const c = this.getCapability(capability);
|
|
1441
|
-
this.state.deleted.push({ capability: c.capability, udid });
|
|
1442
|
-
}
|
|
1443
|
-
removeFromDeletedList(capability, udid) {
|
|
1444
|
-
const c = this.getCapability(capability);
|
|
1445
|
-
const idx = this.state.deleted.findIndex(e => e.capability === c.capability && e.udid === udid);
|
|
1446
|
-
if (idx === -1)
|
|
1447
|
-
return;
|
|
1448
|
-
this.state.deleted.splice(idx, 1);
|
|
1448
|
+
this.state.deleted.push({ capability: c.capability, udid, settings });
|
|
1449
1449
|
}
|
|
1450
1450
|
isOnDeletedList(c, udid) {
|
|
1451
1451
|
const capability = this.getCapability(c);
|
|
@@ -98,11 +98,13 @@ export function concatPaths(path, path2, position, wayId) {
|
|
|
98
98
|
}
|
|
99
99
|
if (position === 'after') {
|
|
100
100
|
append.shift();
|
|
101
|
-
path.push(
|
|
101
|
+
append.forEach(p => path.push(p));
|
|
102
102
|
}
|
|
103
103
|
else {
|
|
104
104
|
path.shift();
|
|
105
|
-
|
|
105
|
+
const newPath = append.concat(path);
|
|
106
|
+
path.length = 0;
|
|
107
|
+
newPath.forEach(p => path.push(p));
|
|
106
108
|
}
|
|
107
109
|
}
|
|
108
110
|
export function splitAtPointInfo(way, split) {
|
|
@@ -107,8 +107,8 @@ function formatRange(low, high, unit, rangePrefix = '') {
|
|
|
107
107
|
const v = high ?? low;
|
|
108
108
|
return v === undefined ? '' : `${Math.round(v)}${unit}`;
|
|
109
109
|
}
|
|
110
|
-
export function getStepTargetText(step, ftp
|
|
111
|
-
const { min: minPower, max: maxPower } =
|
|
110
|
+
export function getStepTargetText(step, ftp) {
|
|
111
|
+
const { min: minPower, max: maxPower } = resolvePowerWatts(step.power, ftp);
|
|
112
112
|
const ascending = step.steady || step.cooldown === false;
|
|
113
113
|
const lowPower = ascending ? minPower : maxPower;
|
|
114
114
|
const highPower = ascending ? maxPower : minPower;
|
|
@@ -164,7 +164,7 @@ let WorkoutRidePageService = (() => {
|
|
|
164
164
|
const current = this.getRideDisplay().getDisplayProperties().workout;
|
|
165
165
|
return {
|
|
166
166
|
...base,
|
|
167
|
-
title: wo
|
|
167
|
+
title: this.getMobileStepTitle(wo),
|
|
168
168
|
graph: this.buildGraphPlan(current, wo.ftp),
|
|
169
169
|
steps: this.buildUpcomingSteps(current, wo.ftp),
|
|
170
170
|
dashboard: this.buildDashboardLine(wo),
|
|
@@ -323,12 +323,13 @@ let WorkoutRidePageService = (() => {
|
|
|
323
323
|
adjustLoad(deltaPct) {
|
|
324
324
|
try {
|
|
325
325
|
if (deltaPct >= 0)
|
|
326
|
-
this.getWorkoutRide().powerUp(deltaPct);
|
|
326
|
+
return this.getWorkoutRide().powerUp(deltaPct);
|
|
327
327
|
else
|
|
328
|
-
this.getWorkoutRide().powerDown(-deltaPct);
|
|
328
|
+
return this.getWorkoutRide().powerDown(-deltaPct);
|
|
329
329
|
}
|
|
330
330
|
catch (err) {
|
|
331
331
|
this.logError(err, 'adjustLoad');
|
|
332
|
+
return undefined;
|
|
332
333
|
}
|
|
333
334
|
}
|
|
334
335
|
onRideStateUpdate(state) {
|
|
@@ -424,7 +425,7 @@ let WorkoutRidePageService = (() => {
|
|
|
424
425
|
if (!limits)
|
|
425
426
|
return empty;
|
|
426
427
|
const currentStep = {
|
|
427
|
-
label: getStepTargetText(limits.step ?? {}, ftp
|
|
428
|
+
label: getStepTargetText(limits.step ?? {}, ftp),
|
|
428
429
|
targetPower: limits.targetPower ?? null,
|
|
429
430
|
duration: limits.duration,
|
|
430
431
|
remaining: limits.remaining,
|
|
@@ -448,12 +449,18 @@ let WorkoutRidePageService = (() => {
|
|
|
448
449
|
const hasMore = currentIndex + 1 + UPCOMING_STEPS_COUNT < flattened.length;
|
|
449
450
|
return { previous, current: currentStep, upcoming, hasMore };
|
|
450
451
|
}
|
|
452
|
+
getMobileStepTitle(wo) {
|
|
453
|
+
const title = wo.title ?? '';
|
|
454
|
+
const name = wo.workout?.name;
|
|
455
|
+
const prefix = name ? `${name}: ` : '';
|
|
456
|
+
return prefix && title.startsWith(prefix) ? title.slice(prefix.length) : title;
|
|
457
|
+
}
|
|
451
458
|
buildDashboardLine(wo) {
|
|
452
459
|
const limits = this.getWorkoutRide().getCurrentLimits();
|
|
453
|
-
const title = wo
|
|
460
|
+
const title = this.getMobileStepTitle(wo);
|
|
454
461
|
if (!limits)
|
|
455
462
|
return { text: title, mode: wo.mode ?? null };
|
|
456
|
-
const target = getStepTargetText(limits.step ?? {}, wo.ftp
|
|
463
|
+
const target = getStepTargetText(limits.step ?? {}, wo.ftp);
|
|
457
464
|
const duration = getStepDuration({ duration: limits.duration });
|
|
458
465
|
const text = title ? `${target} for ${duration} - ${title}` : `${target} for ${duration}`;
|
|
459
466
|
return { text, mode: wo.mode ?? null };
|
|
@@ -277,19 +277,23 @@ let WorkoutRide = (() => {
|
|
|
277
277
|
this.currentLimits.targetPower = Math.min(this.currentLimits.targetPower + deltaVal, this.currentLimits.maxPower);
|
|
278
278
|
this.logEvent({ message: 'workout target power adjusted', targetPower: this.currentLimits.targetPower });
|
|
279
279
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
280
|
-
return;
|
|
280
|
+
return { type: 'targetPower', value: this.currentLimits.targetPower };
|
|
281
281
|
}
|
|
282
|
+
let adjustedFtp;
|
|
282
283
|
if (this.settings?.ftp) {
|
|
283
284
|
this.settings.ftp = this.settings.ftp * (1 + delta / 100);
|
|
284
285
|
this.workoutList.setStartSettings(this.settings);
|
|
285
286
|
this.logEvent({ message: 'workout FTP adjusted', ftp: this.settings.ftp });
|
|
287
|
+
adjustedFtp = Math.round(this.settings.ftp);
|
|
286
288
|
}
|
|
287
289
|
this.manualPowerOffset += delta;
|
|
288
290
|
this.setCurrentLimits();
|
|
289
291
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
292
|
+
return adjustedFtp !== undefined ? { type: 'ftp', value: adjustedFtp } : undefined;
|
|
290
293
|
}
|
|
291
294
|
catch (err) {
|
|
292
295
|
this.logError(err, 'powerUp');
|
|
296
|
+
return undefined;
|
|
293
297
|
}
|
|
294
298
|
}
|
|
295
299
|
powerDown(delta) {
|
|
@@ -303,19 +307,23 @@ let WorkoutRide = (() => {
|
|
|
303
307
|
this.currentLimits.targetPower = Math.max(this.currentLimits.targetPower - deltaVal, this.currentLimits.minPower);
|
|
304
308
|
this.logEvent({ message: 'workout target power adjusted', targetPower: this.currentLimits.targetPower });
|
|
305
309
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
306
|
-
return;
|
|
310
|
+
return { type: 'targetPower', value: this.currentLimits.targetPower };
|
|
307
311
|
}
|
|
312
|
+
let adjustedFtp;
|
|
308
313
|
if (this.settings?.ftp) {
|
|
309
314
|
this.settings.ftp = this.settings.ftp / (1 + delta / 100);
|
|
310
315
|
this.workoutList.setStartSettings(this.settings);
|
|
311
316
|
this.logEvent({ message: 'workout FTP adjusted', ftp: this.settings.ftp });
|
|
317
|
+
adjustedFtp = Math.round(this.settings.ftp);
|
|
312
318
|
}
|
|
313
319
|
this.manualPowerOffset -= delta;
|
|
314
320
|
this.setCurrentLimits();
|
|
315
321
|
this.emit('update', this.getDashboardDisplayProperties());
|
|
322
|
+
return adjustedFtp !== undefined ? { type: 'ftp', value: adjustedFtp } : undefined;
|
|
316
323
|
}
|
|
317
324
|
catch (err) {
|
|
318
325
|
this.logError(err, 'powerDown');
|
|
326
|
+
return undefined;
|
|
319
327
|
}
|
|
320
328
|
}
|
|
321
329
|
toggleCyclingMode() {
|
|
@@ -39,6 +39,8 @@ export declare class DeviceConfigurationService extends IncyclistService {
|
|
|
39
39
|
}): string;
|
|
40
40
|
delete(udid: string, capability?: ExtendedIncyclistCapability, forceSingle?: boolean): void;
|
|
41
41
|
getUdid(deviceSettings: IncyclistDeviceSettings): string;
|
|
42
|
+
protected getUdidForWifiAddressChange(deviceSettings: IncyclistDeviceSettings): string | undefined;
|
|
43
|
+
isEqualDeviceSettings(a: IncyclistDeviceSettings, b: IncyclistDeviceSettings): boolean;
|
|
42
44
|
setDisplayName(deviceSettings: IncyclistDeviceSettings, displayName?: string): void;
|
|
43
45
|
getAdapter(udid: string): IncyclistDeviceAdapter;
|
|
44
46
|
canStartRide(): boolean;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { DeviceData, DeviceSettings, IncyclistCapability, IncyclistDeviceAdapter } from "incyclist-devices";
|
|
2
2
|
import { EnrichedInterfaceSetting } from "../access";
|
|
3
3
|
import { RideServiceCheckFilter } from "../ride";
|
|
4
|
-
import { AdapterInfo } from "../configuration";
|
|
4
|
+
import { AdapterInfo, IncyclistDeviceSettings } from "../configuration";
|
|
5
5
|
export interface DevicePairingData {
|
|
6
6
|
udid: string;
|
|
7
7
|
name: string;
|
|
@@ -41,6 +41,7 @@ export interface PairingState {
|
|
|
41
41
|
export interface DeleteListEntry {
|
|
42
42
|
capability: IncyclistCapability;
|
|
43
43
|
udid: string;
|
|
44
|
+
settings?: IncyclistDeviceSettings;
|
|
44
45
|
}
|
|
45
46
|
export interface InternalPairingState extends PairingState {
|
|
46
47
|
initialized: boolean;
|
|
@@ -136,8 +136,7 @@ export declare class DevicePairingService extends IncyclistService {
|
|
|
136
136
|
protected isPairingWaiting(): NodeJS.Timeout;
|
|
137
137
|
protected _stopDeviceSelection(changed: boolean): Promise<void>;
|
|
138
138
|
private numberOfSelectedCababilities;
|
|
139
|
-
protected addToDeletedList(capability: IncyclistCapability | CapabilityData, udid: string): void;
|
|
140
|
-
protected removeFromDeletedList(capability: IncyclistCapability | CapabilityData, udid: string): void;
|
|
139
|
+
protected addToDeletedList(capability: IncyclistCapability | CapabilityData, udid: string, settings?: IncyclistDeviceSettings): void;
|
|
141
140
|
protected isOnDeletedList(c: IncyclistCapability | CapabilityData, udid: string): boolean;
|
|
142
141
|
mappedCapability(c: CapabilityInformation): CapabilityData;
|
|
143
142
|
protected mappedCapabilities(capabilities: DeviceConfigurationInfo): Array<CapabilityData>;
|
|
@@ -4,10 +4,7 @@ import { WorkoutGraphPlanBar, WorkoutGraphSeriesOptions } from "./types";
|
|
|
4
4
|
export declare const WORKOUT_ZONE_COLORS: string[];
|
|
5
5
|
export declare function getStepDuration(step: StepDefinition): string;
|
|
6
6
|
export declare function getStepPower(step: StepDefinition, ftp?: number): string;
|
|
7
|
-
export declare function getStepTargetText(step: StepDefinition, ftp?: number
|
|
8
|
-
min?: number;
|
|
9
|
-
max?: number;
|
|
10
|
-
}): string;
|
|
7
|
+
export declare function getStepTargetText(step: StepDefinition, ftp?: number): string;
|
|
11
8
|
export interface FlattenedStep {
|
|
12
9
|
step: Step;
|
|
13
10
|
start: number;
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { IncyclistPageService } from "../../../base/pages";
|
|
2
2
|
import type { IObserver } from "../../../base/typedefs";
|
|
3
3
|
import type { CurrentRideState, RideType } from "../../../types";
|
|
4
|
-
import type { WorkoutDisplayProperties } from "../types";
|
|
4
|
+
import type { PowerAdjustmentResult, WorkoutDisplayProperties } from "../types";
|
|
5
5
|
import type { Workout } from "../../base/model";
|
|
6
6
|
import type { StepDefinition } from "../../base/model/types";
|
|
7
7
|
import type { IWorkoutRidePageService, WorkoutDashboardLine, WorkoutGestureHint, WorkoutGraphActuals, WorkoutGraphPlan, WorkoutRideMenuProps, WorkoutRidePageDisplayProps, WorkoutUpcomingSteps } from "./types";
|
|
@@ -37,7 +37,7 @@ export declare class WorkoutRidePageService extends IncyclistPageService impleme
|
|
|
37
37
|
dontShowAgain: boolean;
|
|
38
38
|
}): void;
|
|
39
39
|
onCancelStart(): void;
|
|
40
|
-
adjustLoad(deltaPct: number):
|
|
40
|
+
adjustLoad(deltaPct: number): PowerAdjustmentResult | undefined;
|
|
41
41
|
protected onRideStateUpdate(state: CurrentRideState): void;
|
|
42
42
|
protected onWorkoutUpdate(): void;
|
|
43
43
|
protected onWorkoutFinished(): void;
|
|
@@ -57,6 +57,7 @@ export declare class WorkoutRidePageService extends IncyclistPageService impleme
|
|
|
57
57
|
protected getLoadIncrement(): number;
|
|
58
58
|
protected buildGraphPlan(current: Workout | undefined, ftp: number): WorkoutGraphPlan;
|
|
59
59
|
protected buildUpcomingSteps(current: Workout | undefined, ftp: number): WorkoutUpcomingSteps;
|
|
60
|
+
protected getMobileStepTitle(wo: WorkoutDisplayProperties): string;
|
|
60
61
|
protected buildDashboardLine(wo: WorkoutDisplayProperties): WorkoutDashboardLine;
|
|
61
62
|
protected getStepAbsolutePower(step: StepDefinition, ftp?: number): number | null;
|
|
62
63
|
protected getStepFlags(): {
|
|
@@ -4,7 +4,7 @@ import { Workout } from "../base/model";
|
|
|
4
4
|
import { CurrentStep, PowerLimit, StepDefinition } from "../base/model/types";
|
|
5
5
|
import { WorkoutListService } from "../list";
|
|
6
6
|
import { WorkoutSettings } from "../list/cards/types";
|
|
7
|
-
import { ActiveWorkoutLimit, WorkoutDisplayProperties } from "./types";
|
|
7
|
+
import { ActiveWorkoutLimit, PowerAdjustmentResult, WorkoutDisplayProperties } from "./types";
|
|
8
8
|
export declare class WorkoutRide extends IncyclistService {
|
|
9
9
|
protected manualTimeOffset: number;
|
|
10
10
|
protected manualPowerOffset: number;
|
|
@@ -33,8 +33,8 @@ export declare class WorkoutRide extends IncyclistService {
|
|
|
33
33
|
}): void;
|
|
34
34
|
forward(): void;
|
|
35
35
|
backward(): void;
|
|
36
|
-
powerUp(delta: number):
|
|
37
|
-
powerDown(delta: number):
|
|
36
|
+
powerUp(delta: number): PowerAdjustmentResult | undefined;
|
|
37
|
+
powerDown(delta: number): PowerAdjustmentResult | undefined;
|
|
38
38
|
toggleCyclingMode(): void;
|
|
39
39
|
getDashboardDisplayProperties(): WorkoutDisplayProperties;
|
|
40
40
|
getCurrentLimits(): ActiveWorkoutLimit;
|
|
@@ -15,6 +15,10 @@ export interface ActiveWorkoutLimit extends WorkoutRequest {
|
|
|
15
15
|
remaining: number;
|
|
16
16
|
step?: StepDefinition;
|
|
17
17
|
}
|
|
18
|
+
export interface PowerAdjustmentResult {
|
|
19
|
+
type: 'ftp' | 'targetPower';
|
|
20
|
+
value: number;
|
|
21
|
+
}
|
|
18
22
|
export interface WorkoutDisplayProperties {
|
|
19
23
|
workout?: Workout;
|
|
20
24
|
title?: string;
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-services",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.87",
|
|
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.25",
|
|
11
11
|
"promise.any": "^2.0.6",
|
|
12
12
|
"semver": "^7.7.4",
|
|
13
13
|
"tcx-builder": "^1.1.1",
|
|
@@ -42,7 +42,8 @@
|
|
|
42
42
|
"test:all": "npx jest",
|
|
43
43
|
"test:e2e": "npx jest --coverage -c jest.e2e-config.cjs --coverageDirectory coverage.e2e",
|
|
44
44
|
"test:unit": "npx jest --coverage -c jest.unit-config.cjs ",
|
|
45
|
-
"test": "npx jest
|
|
45
|
+
"test": "npx jest -c jest.unit-config.cjs",
|
|
46
|
+
"coverage": "npx jest --coverage -c jest.unit-config.cjs",
|
|
46
47
|
"dev": "tsc -p tsconfig.esm.json --watch",
|
|
47
48
|
"docgen": "typedoc --options typedoc.json",
|
|
48
49
|
"docgen1": "typedoc --readme none --excludeProtected --excludePrivate --plugin typedoc-plugin-no-inherit --plugin typedoc-plugin-markdown src/index.ts",
|