incyclist-services 1.7.89 → 1.7.91
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/activities/ride/service.js +35 -3
- package/lib/cjs/devices/configuration/service.js +2 -2
- package/lib/cjs/ui/service.js +4 -3
- package/lib/cjs/workouts/page/service.js +8 -1
- package/lib/cjs/workouts/ride/page/service.js +15 -6
- package/lib/esm/activities/ride/service.js +35 -3
- package/lib/esm/devices/configuration/service.js +2 -2
- package/lib/esm/ui/service.js +4 -3
- package/lib/esm/workouts/page/service.js +8 -1
- package/lib/esm/workouts/ride/page/service.js +15 -6
- package/lib/types/activities/ride/service.d.ts +2 -1
- package/lib/types/activities/ride/types.d.ts +7 -0
- package/lib/types/workouts/ride/page/service.d.ts +2 -1
- package/lib/types/workouts/ride/page/types.d.ts +2 -3
- package/package.json +2 -2
|
@@ -48,6 +48,7 @@ const incyclist_devices_1 = require("incyclist-devices");
|
|
|
48
48
|
const devices_1 = require("../../devices");
|
|
49
49
|
const base_1 = require("../base");
|
|
50
50
|
const uuid_1 = require("uuid");
|
|
51
|
+
const workouts_1 = require("../../workouts");
|
|
51
52
|
const route_1 = require("../../routes/base/utils/route");
|
|
52
53
|
const route_2 = require("../../routes/base/model/route");
|
|
53
54
|
const stats_1 = require("./stats");
|
|
@@ -425,14 +426,15 @@ let ActivityRideService = (() => {
|
|
|
425
426
|
const route = this.getRouteList().getSelected();
|
|
426
427
|
const startSettings = this.getRouteList().getStartSettings();
|
|
427
428
|
const isFreeRide = startSettings?.type === 'Free-Ride';
|
|
428
|
-
const
|
|
429
|
+
const showWorkoutSummary = this.activity?.routeType === 'None';
|
|
429
430
|
const showSave = this.activity !== undefined && !this.isSaveDone;
|
|
430
431
|
const showContinue = this.state !== 'completed';
|
|
431
432
|
const hasGPX = this.activity?.logs?.some((log) => !!log.lat && !!log.lng);
|
|
432
|
-
const showMap = hasGPX || isFreeRide ||
|
|
433
|
+
const showMap = hasGPX || isFreeRide || (route?.description?.hasGpx);
|
|
433
434
|
const preview = showMap ? undefined : route?.description?.previewUrl;
|
|
435
|
+
const workoutGraph = showWorkoutSummary ? this.buildWorkoutSummaryGraph(this.activity) : undefined;
|
|
434
436
|
if (!this.isSummaryShown) {
|
|
435
|
-
this.logEvent({ message: 'activity summary shown', showSave, showContinue, showMap, fileLink: this.activity?.fitFileName });
|
|
437
|
+
this.logEvent({ message: 'activity summary shown', showSave, showContinue, showMap, showWorkoutSummary, fileLink: this.activity?.fitFileName });
|
|
436
438
|
}
|
|
437
439
|
this.isSummaryShown = true;
|
|
438
440
|
const props = {
|
|
@@ -440,6 +442,8 @@ let ActivityRideService = (() => {
|
|
|
440
442
|
showSave,
|
|
441
443
|
showContinue,
|
|
442
444
|
showMap,
|
|
445
|
+
showWorkoutSummary,
|
|
446
|
+
workoutGraph,
|
|
443
447
|
showDonate: this.canShowDonate(),
|
|
444
448
|
preview,
|
|
445
449
|
units: this.getUnitConverter().getDefaultUnits()
|
|
@@ -451,6 +455,34 @@ let ActivityRideService = (() => {
|
|
|
451
455
|
return {};
|
|
452
456
|
}
|
|
453
457
|
}
|
|
458
|
+
buildWorkoutSummaryGraph(activity) {
|
|
459
|
+
const workout = activity?.workout;
|
|
460
|
+
if (!workout)
|
|
461
|
+
return undefined;
|
|
462
|
+
const ftp = activity.user?.ftp ?? 0;
|
|
463
|
+
const bars = (0, workouts_1.getWorkoutGraphSeries)(workout, { ftp, absValues: true });
|
|
464
|
+
const lastBarX = bars.length ? bars.at(-1).x : 0;
|
|
465
|
+
const lastLogTime = activity.logs?.length ? activity.logs.at(-1).time : 0;
|
|
466
|
+
const maxXCandidates = [lastLogTime, lastBarX, workout.duration ?? 0].filter(Number.isFinite);
|
|
467
|
+
const maxX = maxXCandidates.length ? Math.max(...maxXCandidates) : 0;
|
|
468
|
+
const maxBarPower = bars.length ? Math.max(...bars.map(b => b.y)) : 0;
|
|
469
|
+
const plan = {
|
|
470
|
+
bars,
|
|
471
|
+
ftp,
|
|
472
|
+
ftpLine: ftp,
|
|
473
|
+
domain: { x: [0, maxX], y: [0, maxBarPower * 1.1] }
|
|
474
|
+
};
|
|
475
|
+
const actuals = {
|
|
476
|
+
power: (activity.logs ?? [])
|
|
477
|
+
.filter(log => Number.isFinite(log.time) && Number.isFinite(log.power))
|
|
478
|
+
.map(log => ({ x: log.time, y: log.power })),
|
|
479
|
+
heartrate: (activity.logs ?? [])
|
|
480
|
+
.filter(log => Number.isFinite(log.time) && Number.isFinite(log.heartrate))
|
|
481
|
+
.map(log => ({ x: log.time, y: log.heartrate })),
|
|
482
|
+
position: -1
|
|
483
|
+
};
|
|
484
|
+
return { plan, actuals };
|
|
485
|
+
}
|
|
454
486
|
canShowDonate() {
|
|
455
487
|
try {
|
|
456
488
|
if (this.isDonateShown) {
|
|
@@ -222,8 +222,8 @@ let DeviceConfigurationService = (() => {
|
|
|
222
222
|
if (c.capability === 'bike')
|
|
223
223
|
return;
|
|
224
224
|
const capability = c.capability;
|
|
225
|
-
if (!capabilties.includes(capability)
|
|
226
|
-
this.delete(udid, capability);
|
|
225
|
+
if (!capabilties.includes(capability)) {
|
|
226
|
+
this.delete(udid, capability, true);
|
|
227
227
|
}
|
|
228
228
|
});
|
|
229
229
|
this.updateUserSettings();
|
package/lib/cjs/ui/service.js
CHANGED
|
@@ -208,7 +208,7 @@ let UserInterfaceServcie = (() => {
|
|
|
208
208
|
try {
|
|
209
209
|
this.startQueueWorker();
|
|
210
210
|
this.startHeartbeatWorker();
|
|
211
|
-
|
|
211
|
+
let sent = false;
|
|
212
212
|
const user = this.getUserSettings().getValue('user', {});
|
|
213
213
|
const id = this.getUserSettings().getValue('uuid', undefined);
|
|
214
214
|
this.getFeatureToggleSync().start(id);
|
|
@@ -223,7 +223,7 @@ let UserInterfaceServcie = (() => {
|
|
|
223
223
|
started: new Date().toISOString()
|
|
224
224
|
};
|
|
225
225
|
if (this.isMobile() || this.isOnline()) {
|
|
226
|
-
this.sendMessage(topic, payload);
|
|
226
|
+
sent = this.sendMessage(topic, payload);
|
|
227
227
|
}
|
|
228
228
|
if (!sent) {
|
|
229
229
|
this.queueMessage(topic, payload);
|
|
@@ -364,7 +364,8 @@ let UserInterfaceServcie = (() => {
|
|
|
364
364
|
version: this.version,
|
|
365
365
|
appVersion: appInfo.getAppVersion(),
|
|
366
366
|
uuid: this.getUserSettings().get('uuid', undefined),
|
|
367
|
-
session: this.session
|
|
367
|
+
session: this.session,
|
|
368
|
+
'app-channel': this.platform
|
|
368
369
|
};
|
|
369
370
|
this.logger.logEvent({ message: 'setting globals', ...globals });
|
|
370
371
|
this.logger.setGlobal(globals);
|
|
@@ -93,7 +93,11 @@ let WorkoutListPageService = (() => {
|
|
|
93
93
|
openPage() {
|
|
94
94
|
try {
|
|
95
95
|
super.openPage();
|
|
96
|
-
|
|
96
|
+
let pageType;
|
|
97
|
+
if (!this.getAppState().hasFeature('MOBILE_WORKOUTS')) {
|
|
98
|
+
pageType = 'placeholder';
|
|
99
|
+
}
|
|
100
|
+
this.logEvent({ message: 'page shown', page: 'Workouts', pageType });
|
|
97
101
|
const { observer } = this.getWorkoutList().open();
|
|
98
102
|
this.listObserver = observer;
|
|
99
103
|
this.listObserver?.on('started', this.listUpdateHandler);
|
|
@@ -323,10 +327,12 @@ let WorkoutListPageService = (() => {
|
|
|
323
327
|
this.importPhase = 'importing';
|
|
324
328
|
this.importingFileName = file?.name;
|
|
325
329
|
this.emitImportUpdate();
|
|
330
|
+
this.logEvent({ message: 'workout import attempted', file: file?.name });
|
|
326
331
|
this.getWorkoutList().import(file, { showImportCards: false })
|
|
327
332
|
.then(([card]) => {
|
|
328
333
|
const group = this.getLastUsedImportGroup();
|
|
329
334
|
observer.emit('success');
|
|
335
|
+
this.logEvent({ message: 'workout import succeeded', file: file?.name, workoutName: card.getTitle(), group });
|
|
330
336
|
if (generation !== this.importGeneration)
|
|
331
337
|
return;
|
|
332
338
|
if (group !== DEFAULT_IMPORT_GROUP)
|
|
@@ -337,6 +343,7 @@ let WorkoutListPageService = (() => {
|
|
|
337
343
|
})
|
|
338
344
|
.catch((err) => {
|
|
339
345
|
observer.emit('error', err);
|
|
346
|
+
this.logEvent({ message: 'workout import failed', file: file?.name, error: err?.message });
|
|
340
347
|
if (generation !== this.importGeneration)
|
|
341
348
|
return;
|
|
342
349
|
this.importPhase = 'error';
|
|
@@ -91,8 +91,8 @@ let WorkoutRidePageService = (() => {
|
|
|
91
91
|
this.workoutEventHandler['update'] = this.onWorkoutUpdate.bind(this);
|
|
92
92
|
this.workoutEventHandler['forward'] = this.onWorkoutUpdate.bind(this);
|
|
93
93
|
this.workoutEventHandler['backward'] = this.onWorkoutUpdate.bind(this);
|
|
94
|
-
this.workoutEventHandler['completed'] = this.
|
|
95
|
-
this.workoutEventHandler['stopped'] = this.
|
|
94
|
+
this.workoutEventHandler['completed'] = this.onFinished.bind(this);
|
|
95
|
+
this.workoutEventHandler['stopped'] = this.onFinished.bind(this);
|
|
96
96
|
}
|
|
97
97
|
openPage(simulate) {
|
|
98
98
|
try {
|
|
@@ -119,7 +119,7 @@ let WorkoutRidePageService = (() => {
|
|
|
119
119
|
try {
|
|
120
120
|
gd_eventlog_1.EventLogger.setGlobalConfig('page', null);
|
|
121
121
|
this.logEvent({ message: 'page closed', page: 'WorkoutRide' });
|
|
122
|
-
this.getRideDisplay().stop(
|
|
122
|
+
this.getRideDisplay().stop();
|
|
123
123
|
this.unregisterRideEventHandlers();
|
|
124
124
|
this.unsubscribeFromWorkoutObserver();
|
|
125
125
|
this.menuProps = null;
|
|
@@ -243,8 +243,7 @@ let WorkoutRidePageService = (() => {
|
|
|
243
243
|
}
|
|
244
244
|
onStop() {
|
|
245
245
|
try {
|
|
246
|
-
this.
|
|
247
|
-
this.emitNavigateBack();
|
|
246
|
+
this.finishRide();
|
|
248
247
|
}
|
|
249
248
|
catch (err) {
|
|
250
249
|
this.logError(err, 'onStop');
|
|
@@ -353,7 +352,17 @@ let WorkoutRidePageService = (() => {
|
|
|
353
352
|
onWorkoutUpdate() {
|
|
354
353
|
this.updatePageDisplay();
|
|
355
354
|
}
|
|
356
|
-
|
|
355
|
+
onFinished() {
|
|
356
|
+
try {
|
|
357
|
+
this.menuProps = { showResume: false, finished: true, canStepBack: false, canStepForward: false };
|
|
358
|
+
this.updatePageDisplay();
|
|
359
|
+
}
|
|
360
|
+
catch (err) {
|
|
361
|
+
this.logError(err, 'onFinished');
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
finishRide() {
|
|
365
|
+
this.getRideDisplay().stop(true);
|
|
357
366
|
this.emitNavigateBack();
|
|
358
367
|
}
|
|
359
368
|
subscribeToWorkoutObserver() {
|
|
@@ -42,6 +42,7 @@ import { IncyclistCapability } from "incyclist-devices";
|
|
|
42
42
|
import { useDeviceConfiguration, useDeviceRide } from "../../devices";
|
|
43
43
|
import { ActivitiesRepository, ActivityConverter, ActivityConverterFactory, DB_VERSION, DEFAULT_SPORT_ACTIVITY_TITLE } from "../base";
|
|
44
44
|
import { v4 as generateUUID } from 'uuid';
|
|
45
|
+
import { getWorkoutGraphSeries } from "../../workouts";
|
|
45
46
|
import { addDetails, checkIsLoop, getElevationGainAt, getNextPosition, getPosition, getRouteHash, validateRoute } from "../../routes/base/utils/route";
|
|
46
47
|
import { Route } from "../../routes/base/model/route";
|
|
47
48
|
import { ActivityStatsCalculator } from "./stats";
|
|
@@ -419,14 +420,15 @@ let ActivityRideService = (() => {
|
|
|
419
420
|
const route = this.getRouteList().getSelected();
|
|
420
421
|
const startSettings = this.getRouteList().getStartSettings();
|
|
421
422
|
const isFreeRide = startSettings?.type === 'Free-Ride';
|
|
422
|
-
const
|
|
423
|
+
const showWorkoutSummary = this.activity?.routeType === 'None';
|
|
423
424
|
const showSave = this.activity !== undefined && !this.isSaveDone;
|
|
424
425
|
const showContinue = this.state !== 'completed';
|
|
425
426
|
const hasGPX = this.activity?.logs?.some((log) => !!log.lat && !!log.lng);
|
|
426
|
-
const showMap = hasGPX || isFreeRide ||
|
|
427
|
+
const showMap = hasGPX || isFreeRide || (route?.description?.hasGpx);
|
|
427
428
|
const preview = showMap ? undefined : route?.description?.previewUrl;
|
|
429
|
+
const workoutGraph = showWorkoutSummary ? this.buildWorkoutSummaryGraph(this.activity) : undefined;
|
|
428
430
|
if (!this.isSummaryShown) {
|
|
429
|
-
this.logEvent({ message: 'activity summary shown', showSave, showContinue, showMap, fileLink: this.activity?.fitFileName });
|
|
431
|
+
this.logEvent({ message: 'activity summary shown', showSave, showContinue, showMap, showWorkoutSummary, fileLink: this.activity?.fitFileName });
|
|
430
432
|
}
|
|
431
433
|
this.isSummaryShown = true;
|
|
432
434
|
const props = {
|
|
@@ -434,6 +436,8 @@ let ActivityRideService = (() => {
|
|
|
434
436
|
showSave,
|
|
435
437
|
showContinue,
|
|
436
438
|
showMap,
|
|
439
|
+
showWorkoutSummary,
|
|
440
|
+
workoutGraph,
|
|
437
441
|
showDonate: this.canShowDonate(),
|
|
438
442
|
preview,
|
|
439
443
|
units: this.getUnitConverter().getDefaultUnits()
|
|
@@ -445,6 +449,34 @@ let ActivityRideService = (() => {
|
|
|
445
449
|
return {};
|
|
446
450
|
}
|
|
447
451
|
}
|
|
452
|
+
buildWorkoutSummaryGraph(activity) {
|
|
453
|
+
const workout = activity?.workout;
|
|
454
|
+
if (!workout)
|
|
455
|
+
return undefined;
|
|
456
|
+
const ftp = activity.user?.ftp ?? 0;
|
|
457
|
+
const bars = getWorkoutGraphSeries(workout, { ftp, absValues: true });
|
|
458
|
+
const lastBarX = bars.length ? bars.at(-1).x : 0;
|
|
459
|
+
const lastLogTime = activity.logs?.length ? activity.logs.at(-1).time : 0;
|
|
460
|
+
const maxXCandidates = [lastLogTime, lastBarX, workout.duration ?? 0].filter(Number.isFinite);
|
|
461
|
+
const maxX = maxXCandidates.length ? Math.max(...maxXCandidates) : 0;
|
|
462
|
+
const maxBarPower = bars.length ? Math.max(...bars.map(b => b.y)) : 0;
|
|
463
|
+
const plan = {
|
|
464
|
+
bars,
|
|
465
|
+
ftp,
|
|
466
|
+
ftpLine: ftp,
|
|
467
|
+
domain: { x: [0, maxX], y: [0, maxBarPower * 1.1] }
|
|
468
|
+
};
|
|
469
|
+
const actuals = {
|
|
470
|
+
power: (activity.logs ?? [])
|
|
471
|
+
.filter(log => Number.isFinite(log.time) && Number.isFinite(log.power))
|
|
472
|
+
.map(log => ({ x: log.time, y: log.power })),
|
|
473
|
+
heartrate: (activity.logs ?? [])
|
|
474
|
+
.filter(log => Number.isFinite(log.time) && Number.isFinite(log.heartrate))
|
|
475
|
+
.map(log => ({ x: log.time, y: log.heartrate })),
|
|
476
|
+
position: -1
|
|
477
|
+
};
|
|
478
|
+
return { plan, actuals };
|
|
479
|
+
}
|
|
448
480
|
canShowDonate() {
|
|
449
481
|
try {
|
|
450
482
|
if (this.isDonateShown) {
|
|
@@ -216,8 +216,8 @@ let DeviceConfigurationService = (() => {
|
|
|
216
216
|
if (c.capability === 'bike')
|
|
217
217
|
return;
|
|
218
218
|
const capability = c.capability;
|
|
219
|
-
if (!capabilties.includes(capability)
|
|
220
|
-
this.delete(udid, capability);
|
|
219
|
+
if (!capabilties.includes(capability)) {
|
|
220
|
+
this.delete(udid, capability, true);
|
|
221
221
|
}
|
|
222
222
|
});
|
|
223
223
|
this.updateUserSettings();
|
package/lib/esm/ui/service.js
CHANGED
|
@@ -205,7 +205,7 @@ let UserInterfaceServcie = (() => {
|
|
|
205
205
|
try {
|
|
206
206
|
this.startQueueWorker();
|
|
207
207
|
this.startHeartbeatWorker();
|
|
208
|
-
|
|
208
|
+
let sent = false;
|
|
209
209
|
const user = this.getUserSettings().getValue('user', {});
|
|
210
210
|
const id = this.getUserSettings().getValue('uuid', undefined);
|
|
211
211
|
this.getFeatureToggleSync().start(id);
|
|
@@ -220,7 +220,7 @@ let UserInterfaceServcie = (() => {
|
|
|
220
220
|
started: new Date().toISOString()
|
|
221
221
|
};
|
|
222
222
|
if (this.isMobile() || this.isOnline()) {
|
|
223
|
-
this.sendMessage(topic, payload);
|
|
223
|
+
sent = this.sendMessage(topic, payload);
|
|
224
224
|
}
|
|
225
225
|
if (!sent) {
|
|
226
226
|
this.queueMessage(topic, payload);
|
|
@@ -361,7 +361,8 @@ let UserInterfaceServcie = (() => {
|
|
|
361
361
|
version: this.version,
|
|
362
362
|
appVersion: appInfo.getAppVersion(),
|
|
363
363
|
uuid: this.getUserSettings().get('uuid', undefined),
|
|
364
|
-
session: this.session
|
|
364
|
+
session: this.session,
|
|
365
|
+
'app-channel': this.platform
|
|
365
366
|
};
|
|
366
367
|
this.logger.logEvent({ message: 'setting globals', ...globals });
|
|
367
368
|
this.logger.setGlobal(globals);
|
|
@@ -90,7 +90,11 @@ let WorkoutListPageService = (() => {
|
|
|
90
90
|
openPage() {
|
|
91
91
|
try {
|
|
92
92
|
super.openPage();
|
|
93
|
-
|
|
93
|
+
let pageType;
|
|
94
|
+
if (!this.getAppState().hasFeature('MOBILE_WORKOUTS')) {
|
|
95
|
+
pageType = 'placeholder';
|
|
96
|
+
}
|
|
97
|
+
this.logEvent({ message: 'page shown', page: 'Workouts', pageType });
|
|
94
98
|
const { observer } = this.getWorkoutList().open();
|
|
95
99
|
this.listObserver = observer;
|
|
96
100
|
this.listObserver?.on('started', this.listUpdateHandler);
|
|
@@ -320,10 +324,12 @@ let WorkoutListPageService = (() => {
|
|
|
320
324
|
this.importPhase = 'importing';
|
|
321
325
|
this.importingFileName = file?.name;
|
|
322
326
|
this.emitImportUpdate();
|
|
327
|
+
this.logEvent({ message: 'workout import attempted', file: file?.name });
|
|
323
328
|
this.getWorkoutList().import(file, { showImportCards: false })
|
|
324
329
|
.then(([card]) => {
|
|
325
330
|
const group = this.getLastUsedImportGroup();
|
|
326
331
|
observer.emit('success');
|
|
332
|
+
this.logEvent({ message: 'workout import succeeded', file: file?.name, workoutName: card.getTitle(), group });
|
|
327
333
|
if (generation !== this.importGeneration)
|
|
328
334
|
return;
|
|
329
335
|
if (group !== DEFAULT_IMPORT_GROUP)
|
|
@@ -334,6 +340,7 @@ let WorkoutListPageService = (() => {
|
|
|
334
340
|
})
|
|
335
341
|
.catch((err) => {
|
|
336
342
|
observer.emit('error', err);
|
|
343
|
+
this.logEvent({ message: 'workout import failed', file: file?.name, error: err?.message });
|
|
337
344
|
if (generation !== this.importGeneration)
|
|
338
345
|
return;
|
|
339
346
|
this.importPhase = 'error';
|
|
@@ -88,8 +88,8 @@ let WorkoutRidePageService = (() => {
|
|
|
88
88
|
this.workoutEventHandler['update'] = this.onWorkoutUpdate.bind(this);
|
|
89
89
|
this.workoutEventHandler['forward'] = this.onWorkoutUpdate.bind(this);
|
|
90
90
|
this.workoutEventHandler['backward'] = this.onWorkoutUpdate.bind(this);
|
|
91
|
-
this.workoutEventHandler['completed'] = this.
|
|
92
|
-
this.workoutEventHandler['stopped'] = this.
|
|
91
|
+
this.workoutEventHandler['completed'] = this.onFinished.bind(this);
|
|
92
|
+
this.workoutEventHandler['stopped'] = this.onFinished.bind(this);
|
|
93
93
|
}
|
|
94
94
|
openPage(simulate) {
|
|
95
95
|
try {
|
|
@@ -116,7 +116,7 @@ let WorkoutRidePageService = (() => {
|
|
|
116
116
|
try {
|
|
117
117
|
EventLogger.setGlobalConfig('page', null);
|
|
118
118
|
this.logEvent({ message: 'page closed', page: 'WorkoutRide' });
|
|
119
|
-
this.getRideDisplay().stop(
|
|
119
|
+
this.getRideDisplay().stop();
|
|
120
120
|
this.unregisterRideEventHandlers();
|
|
121
121
|
this.unsubscribeFromWorkoutObserver();
|
|
122
122
|
this.menuProps = null;
|
|
@@ -240,8 +240,7 @@ let WorkoutRidePageService = (() => {
|
|
|
240
240
|
}
|
|
241
241
|
onStop() {
|
|
242
242
|
try {
|
|
243
|
-
this.
|
|
244
|
-
this.emitNavigateBack();
|
|
243
|
+
this.finishRide();
|
|
245
244
|
}
|
|
246
245
|
catch (err) {
|
|
247
246
|
this.logError(err, 'onStop');
|
|
@@ -350,7 +349,17 @@ let WorkoutRidePageService = (() => {
|
|
|
350
349
|
onWorkoutUpdate() {
|
|
351
350
|
this.updatePageDisplay();
|
|
352
351
|
}
|
|
353
|
-
|
|
352
|
+
onFinished() {
|
|
353
|
+
try {
|
|
354
|
+
this.menuProps = { showResume: false, finished: true, canStepBack: false, canStepForward: false };
|
|
355
|
+
this.updatePageDisplay();
|
|
356
|
+
}
|
|
357
|
+
catch (err) {
|
|
358
|
+
this.logError(err, 'onFinished');
|
|
359
|
+
}
|
|
360
|
+
}
|
|
361
|
+
finishRide() {
|
|
362
|
+
this.getRideDisplay().stop(true);
|
|
354
363
|
this.emitNavigateBack();
|
|
355
364
|
}
|
|
356
365
|
subscribeToWorkoutObserver() {
|
|
@@ -6,7 +6,7 @@ import { ActivitiesRepository, ActivityConverterFactory, ActivityDetails, Activi
|
|
|
6
6
|
import { FreeRideStartSettings } from "../../routes/list/types";
|
|
7
7
|
import { RouteSettings } from "../../routes/list/cards/types";
|
|
8
8
|
import { RoutePoint } from "../../routes/base/types";
|
|
9
|
-
import { ActivityDashboardDataItem, ActivityState, ActivitySummaryDisplayProperties } from "./types";
|
|
9
|
+
import { ActivityDashboardDataItem, ActivityState, ActivitySummaryDisplayProperties, ActivityWorkoutSummaryGraph } from "./types";
|
|
10
10
|
import { Route } from "../../routes/base/model/route";
|
|
11
11
|
import { ActivityStatsCalculator } from "./stats";
|
|
12
12
|
import { ActivityDuration } from "./duration";
|
|
@@ -146,6 +146,7 @@ export declare class ActivityRideService extends IncyclistService {
|
|
|
146
146
|
elevationGain?: undefined;
|
|
147
147
|
};
|
|
148
148
|
getActivitySummaryDisplayProperties(): ActivitySummaryDisplayProperties;
|
|
149
|
+
protected buildWorkoutSummaryGraph(activity?: ActivityDetails): ActivityWorkoutSummaryGraph | undefined;
|
|
149
150
|
protected canShowDonate(): boolean;
|
|
150
151
|
onDonateClicked(): void;
|
|
151
152
|
getActivity(): ActivityDetails;
|
|
@@ -2,12 +2,19 @@ import { HealthStatus } from "../../devices";
|
|
|
2
2
|
import { Dimension, Unit } from "../../i18n";
|
|
3
3
|
import { RoutePoint } from "../../types";
|
|
4
4
|
import { ActivityDetailsUI } from "../base";
|
|
5
|
+
import { WorkoutGraphActuals, WorkoutGraphPlan } from "../../workouts";
|
|
5
6
|
export type ActivityState = 'ininitalized' | 'active' | 'paused' | 'completed' | 'idle';
|
|
7
|
+
export type ActivityWorkoutSummaryGraph = {
|
|
8
|
+
plan: WorkoutGraphPlan;
|
|
9
|
+
actuals: WorkoutGraphActuals;
|
|
10
|
+
};
|
|
6
11
|
export type ActivitySummaryDisplayProperties = {
|
|
7
12
|
activity?: ActivityDetailsUI;
|
|
8
13
|
showSave?: boolean;
|
|
9
14
|
showContinue?: boolean;
|
|
10
15
|
showMap?: boolean;
|
|
16
|
+
showWorkoutSummary?: boolean;
|
|
17
|
+
workoutGraph?: ActivityWorkoutSummaryGraph;
|
|
11
18
|
preview?: string;
|
|
12
19
|
units?: Record<Dimension, Unit>;
|
|
13
20
|
};
|
|
@@ -40,7 +40,8 @@ export declare class WorkoutRidePageService extends IncyclistPageService impleme
|
|
|
40
40
|
adjustLoad(deltaPct: number): PowerAdjustmentResult | undefined;
|
|
41
41
|
protected onRideStateUpdate(state: CurrentRideState): void;
|
|
42
42
|
protected onWorkoutUpdate(): void;
|
|
43
|
-
protected
|
|
43
|
+
protected onFinished(): void;
|
|
44
|
+
protected finishRide(): void;
|
|
44
45
|
protected subscribeToWorkoutObserver(): void;
|
|
45
46
|
protected unsubscribeFromWorkoutObserver(): void;
|
|
46
47
|
protected registerRideEventHandlers(): void;
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import type { IObserver } from "../../../base/typedefs";
|
|
2
2
|
import type { IPageService } from "../../../base/pages";
|
|
3
|
-
import type { RidePageDisplayProps } from "../../../ride/page/types";
|
|
3
|
+
import type { RideMenuProps, RidePageDisplayProps } from "../../../ride/page/types";
|
|
4
4
|
import type { WorkoutGraphPlanBar } from "../../base/graph/types";
|
|
5
5
|
export interface WorkoutGraphPoint {
|
|
6
6
|
x: number;
|
|
@@ -37,8 +37,7 @@ export interface WorkoutDashboardLine {
|
|
|
37
37
|
text: string;
|
|
38
38
|
mode: string | null;
|
|
39
39
|
}
|
|
40
|
-
export interface WorkoutRideMenuProps {
|
|
41
|
-
showResume: boolean;
|
|
40
|
+
export interface WorkoutRideMenuProps extends RideMenuProps {
|
|
42
41
|
canStepBack: boolean;
|
|
43
42
|
canStepForward: boolean;
|
|
44
43
|
}
|
package/package.json
CHANGED
|
@@ -1,13 +1,13 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-services",
|
|
3
|
-
"version": "1.7.
|
|
3
|
+
"version": "1.7.91",
|
|
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.27",
|
|
11
11
|
"promise.any": "^2.0.6",
|
|
12
12
|
"semver": "^7.7.4",
|
|
13
13
|
"tcx-builder": "^1.1.1",
|