incyclist-services 1.7.76 → 1.7.78

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.
Files changed (66) hide show
  1. package/lib/cjs/activities/list/service.js +1 -1
  2. package/lib/cjs/activities/ride/service.js +2 -1
  3. package/lib/cjs/workouts/base/graph/index.js +18 -0
  4. package/lib/cjs/workouts/base/graph/series.js +205 -0
  5. package/lib/cjs/workouts/base/graph/types.js +2 -0
  6. package/lib/cjs/workouts/base/model/index.js +0 -1
  7. package/lib/cjs/workouts/calendar/service.js +14 -0
  8. package/lib/cjs/workouts/index.js +2 -0
  9. package/lib/cjs/workouts/list/cards/index.js +0 -1
  10. package/lib/cjs/workouts/list/index.js +0 -1
  11. package/lib/cjs/workouts/list/pageService.js +362 -5
  12. package/lib/cjs/workouts/list/service.js +39 -12
  13. package/lib/cjs/workouts/page/index.js +17 -0
  14. package/lib/cjs/workouts/page/service.js +455 -0
  15. package/lib/cjs/workouts/page/types.js +2 -0
  16. package/lib/cjs/workouts/ride/index.js +1 -0
  17. package/lib/cjs/workouts/ride/page/index.js +18 -0
  18. package/lib/cjs/workouts/ride/page/service.js +498 -0
  19. package/lib/cjs/workouts/ride/page/types.js +2 -0
  20. package/lib/cjs/workouts/ride/service.js +1 -1
  21. package/lib/cjs/workouts/types.js +2 -0
  22. package/lib/esm/activities/list/service.js +1 -1
  23. package/lib/esm/activities/ride/service.js +2 -1
  24. package/lib/esm/workouts/base/graph/index.js +2 -0
  25. package/lib/esm/workouts/base/graph/series.js +197 -0
  26. package/lib/esm/workouts/base/graph/types.js +1 -0
  27. package/lib/esm/workouts/base/model/index.js +0 -1
  28. package/lib/esm/workouts/calendar/service.js +14 -0
  29. package/lib/esm/workouts/index.js +2 -0
  30. package/lib/esm/workouts/list/cards/index.js +0 -1
  31. package/lib/esm/workouts/list/index.js +0 -1
  32. package/lib/esm/workouts/list/pageService.js +362 -5
  33. package/lib/esm/workouts/list/service.js +39 -12
  34. package/lib/esm/workouts/page/index.js +1 -0
  35. package/lib/esm/workouts/page/service.js +451 -0
  36. package/lib/esm/workouts/page/types.js +1 -0
  37. package/lib/esm/workouts/ride/index.js +1 -0
  38. package/lib/esm/workouts/ride/page/index.js +2 -0
  39. package/lib/esm/workouts/ride/page/service.js +494 -0
  40. package/lib/esm/workouts/ride/page/types.js +1 -0
  41. package/lib/esm/workouts/ride/service.js +1 -1
  42. package/lib/esm/workouts/types.js +1 -0
  43. package/lib/types/types.d.ts +1 -0
  44. package/lib/types/workouts/base/graph/index.d.ts +2 -0
  45. package/lib/types/workouts/base/graph/series.d.ts +18 -0
  46. package/lib/types/workouts/base/graph/types.d.ts +11 -0
  47. package/lib/types/workouts/base/model/index.d.ts +0 -1
  48. package/lib/types/workouts/base/parsers/intervals/parser.d.ts +2 -1
  49. package/lib/types/workouts/calendar/service.d.ts +1 -0
  50. package/lib/types/workouts/index.d.ts +2 -0
  51. package/lib/types/workouts/list/cards/index.d.ts +0 -1
  52. package/lib/types/workouts/list/index.d.ts +0 -1
  53. package/lib/types/workouts/list/pageService.d.ts +136 -4
  54. package/lib/types/workouts/list/service.d.ts +4 -0
  55. package/lib/types/workouts/list/types.d.ts +1 -1
  56. package/lib/types/workouts/page/index.d.ts +1 -0
  57. package/lib/types/workouts/page/service.d.ts +57 -0
  58. package/lib/types/workouts/page/types.d.ts +95 -0
  59. package/lib/types/workouts/ride/index.d.ts +1 -0
  60. package/lib/types/workouts/ride/page/index.d.ts +2 -0
  61. package/lib/types/workouts/ride/page/service.d.ts +70 -0
  62. package/lib/types/workouts/ride/page/types.d.ts +71 -0
  63. package/lib/types/workouts/ride/service.d.ts +2 -1
  64. package/lib/types/workouts/ride/types.d.ts +3 -0
  65. package/lib/types/workouts/types.d.ts +8 -0
  66. package/package.json +1 -1
@@ -0,0 +1,494 @@
1
+ var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
2
+ var useValue = arguments.length > 2;
3
+ for (var i = 0; i < initializers.length; i++) {
4
+ value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
5
+ }
6
+ return useValue ? value : void 0;
7
+ };
8
+ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
9
+ function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
10
+ var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
11
+ var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
12
+ var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
13
+ var _, done = false;
14
+ for (var i = decorators.length - 1; i >= 0; i--) {
15
+ var context = {};
16
+ for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
17
+ for (var p in contextIn.access) context.access[p] = contextIn.access[p];
18
+ context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
19
+ var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
20
+ if (kind === "accessor") {
21
+ if (result === void 0) continue;
22
+ if (result === null || typeof result !== "object") throw new TypeError("Object expected");
23
+ if (_ = accept(result.get)) descriptor.get = _;
24
+ if (_ = accept(result.set)) descriptor.set = _;
25
+ if (_ = accept(result.init)) initializers.unshift(_);
26
+ }
27
+ else if (_ = accept(result)) {
28
+ if (kind === "field") initializers.unshift(_);
29
+ else descriptor[key] = _;
30
+ }
31
+ }
32
+ if (target) Object.defineProperty(target, contextIn.name, descriptor);
33
+ done = true;
34
+ };
35
+ import { EventLogger } from "gd-eventlog";
36
+ import { Injectable } from "../../../base/decorators";
37
+ import { Singleton } from "../../../base/types";
38
+ import { IncyclistPageService } from "../../../base/pages";
39
+ import { useRideDisplay } from "../../../ride/display";
40
+ import { useActivityRide } from "../../../activities";
41
+ import { useWorkoutRide } from "../service";
42
+ import { getFlattenedSteps, getStepDuration, getStepTargetText, getWorkoutGraphSeries } from "../../base/graph";
43
+ const BACKGROUND_PAUSE_TIMEOUT_MS = 300000;
44
+ const UPCOMING_STEPS_COUNT = 3;
45
+ const DEFAULT_LOAD_INCREMENT = 1;
46
+ let WorkoutRidePageService = (() => {
47
+ let _classDecorators = [Singleton];
48
+ let _classDescriptor;
49
+ let _classExtraInitializers = [];
50
+ let _classThis;
51
+ let _classSuper = IncyclistPageService;
52
+ let _instanceExtraInitializers = [];
53
+ let _getRideDisplay_decorators;
54
+ let _getWorkoutRide_decorators;
55
+ let _getActivityRide_decorators;
56
+ var WorkoutRidePageService = class extends _classSuper {
57
+ static { _classThis = this; }
58
+ static {
59
+ const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
60
+ _getRideDisplay_decorators = [Injectable];
61
+ _getWorkoutRide_decorators = [Injectable];
62
+ _getActivityRide_decorators = [Injectable];
63
+ __esDecorate(this, null, _getRideDisplay_decorators, { kind: "method", name: "getRideDisplay", static: false, private: false, access: { has: obj => "getRideDisplay" in obj, get: obj => obj.getRideDisplay }, metadata: _metadata }, null, _instanceExtraInitializers);
64
+ __esDecorate(this, null, _getWorkoutRide_decorators, { kind: "method", name: "getWorkoutRide", static: false, private: false, access: { has: obj => "getWorkoutRide" in obj, get: obj => obj.getWorkoutRide }, metadata: _metadata }, null, _instanceExtraInitializers);
65
+ __esDecorate(this, null, _getActivityRide_decorators, { kind: "method", name: "getActivityRide", static: false, private: false, access: { has: obj => "getActivityRide" in obj, get: obj => obj.getActivityRide }, metadata: _metadata }, null, _instanceExtraInitializers);
66
+ __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
67
+ WorkoutRidePageService = _classThis = _classDescriptor.value;
68
+ if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
69
+ __runInitializers(_classThis, _classExtraInitializers);
70
+ }
71
+ rideEventHandler = (__runInitializers(this, _instanceExtraInitializers), {});
72
+ workoutEventHandler = {};
73
+ workoutObserverSubscribed = false;
74
+ backgroundTimer;
75
+ backgroundPausedByService = false;
76
+ menuProps = null;
77
+ isInitialized = false;
78
+ constructor() {
79
+ super('WorkoutRidePage');
80
+ this.rideEventHandler['state-update'] = this.onRideStateUpdate.bind(this);
81
+ this.workoutEventHandler['step-changed'] = this.onWorkoutUpdate.bind(this);
82
+ this.workoutEventHandler['update'] = this.onWorkoutUpdate.bind(this);
83
+ this.workoutEventHandler['forward'] = this.onWorkoutUpdate.bind(this);
84
+ this.workoutEventHandler['backward'] = this.onWorkoutUpdate.bind(this);
85
+ this.workoutEventHandler['completed'] = this.onWorkoutFinished.bind(this);
86
+ this.workoutEventHandler['stopped'] = this.onWorkoutFinished.bind(this);
87
+ }
88
+ openPage(simulate) {
89
+ try {
90
+ this.logEvent({ message: 'page shown', page: 'WorkoutRide' });
91
+ EventLogger.setGlobalConfig('page', 'WorkoutRide');
92
+ super.openPage();
93
+ try {
94
+ const service = this.getRideDisplay();
95
+ if (!this.isInitialized) {
96
+ service.init();
97
+ this.isInitialized = true;
98
+ }
99
+ this.registerRideEventHandlers();
100
+ this.subscribeToWorkoutObserver();
101
+ service.start(simulate);
102
+ }
103
+ catch (err) {
104
+ this.logError(err, 'openPage');
105
+ }
106
+ }
107
+ catch (err) {
108
+ this.logError(err, 'openPage');
109
+ }
110
+ return this.getPageObserver();
111
+ }
112
+ closePage() {
113
+ try {
114
+ EventLogger.setGlobalConfig('page', null);
115
+ this.logEvent({ message: 'page closed', page: 'WorkoutRide' });
116
+ this.getRideDisplay().stop(true);
117
+ this.unregisterRideEventHandlers();
118
+ this.unsubscribeFromWorkoutObserver();
119
+ this.menuProps = null;
120
+ this.isInitialized = false;
121
+ super.closePage();
122
+ }
123
+ catch (err) {
124
+ this.logError(err, 'closePage');
125
+ }
126
+ }
127
+ async pausePage() {
128
+ try {
129
+ this.backgroundTimer = setTimeout(() => {
130
+ this.getRideDisplay().pause('device');
131
+ this.backgroundPausedByService = true;
132
+ }, BACKGROUND_PAUSE_TIMEOUT_MS);
133
+ return super.pausePage();
134
+ }
135
+ catch (err) {
136
+ this.logError(err, 'pausePage');
137
+ }
138
+ }
139
+ async resumePage() {
140
+ try {
141
+ if (this.backgroundTimer) {
142
+ clearTimeout(this.backgroundTimer);
143
+ }
144
+ return super.resumePage();
145
+ }
146
+ catch (err) {
147
+ this.logError(err, 'resumePage');
148
+ }
149
+ }
150
+ getRideObserver() {
151
+ return this.rideObserver ?? null;
152
+ }
153
+ getPageDisplayProps() {
154
+ try {
155
+ const rideType = this.getRideDisplay().getRideType();
156
+ if (rideType !== 'Workout') {
157
+ this.logError(new Error(`unexpected ride type '${rideType}' for WorkoutRidePage`), 'getPageDisplayProps');
158
+ return this.getEmptyDisplayProps();
159
+ }
160
+ const base = this.buildBaseProps();
161
+ const wo = this.getWorkoutRide().getDashboardDisplayProperties();
162
+ const current = this.getRideDisplay().getDisplayProperties().workout;
163
+ return {
164
+ ...base,
165
+ title: wo.title ?? '',
166
+ graph: this.buildGraphPlan(current, wo.ftp),
167
+ steps: this.buildUpcomingSteps(current, wo.ftp),
168
+ dashboard: this.buildDashboardLine(wo)
169
+ };
170
+ }
171
+ catch (err) {
172
+ this.logError(err, 'getPageDisplayProps');
173
+ return this.getEmptyDisplayProps();
174
+ }
175
+ }
176
+ getGraphActuals() {
177
+ try {
178
+ const state = this.getRideDisplay().getState();
179
+ if (state === 'Idle' || state === 'Starting' || state === 'Started') {
180
+ return { power: [], heartrate: [], position: 0 };
181
+ }
182
+ const logs = this.getActivityRide().getActivity()?.logs ?? [];
183
+ const power = [];
184
+ const heartrate = [];
185
+ logs.forEach(log => {
186
+ if (log.power !== undefined)
187
+ power.push({ x: log.time, y: log.power });
188
+ if (log.heartrate !== undefined)
189
+ heartrate.push({ x: log.time, y: log.heartrate });
190
+ });
191
+ return { power, heartrate, position: this.getElapsedActivityTime() };
192
+ }
193
+ catch (err) {
194
+ this.logError(err, 'getGraphActuals');
195
+ return { power: [], heartrate: [], position: 0 };
196
+ }
197
+ }
198
+ onMenuOpen() {
199
+ try {
200
+ const state = this.getRideDisplay().getState();
201
+ this.menuProps = { showResume: state === 'Paused', ...this.getStepFlags() };
202
+ this.updatePageDisplay();
203
+ }
204
+ catch (err) {
205
+ this.logError(err, 'onMenuOpen');
206
+ }
207
+ }
208
+ onMenuClose() {
209
+ try {
210
+ this.menuProps = null;
211
+ this.updatePageDisplay();
212
+ }
213
+ catch (err) {
214
+ this.logError(err, 'onMenuClose');
215
+ }
216
+ }
217
+ onPause() {
218
+ try {
219
+ this.getRideDisplay().pause('user');
220
+ this.menuProps = { showResume: true, ...this.getStepFlags() };
221
+ this.updatePageDisplay();
222
+ }
223
+ catch (err) {
224
+ this.logError(err, 'onPause');
225
+ }
226
+ }
227
+ onResume() {
228
+ try {
229
+ this.getRideDisplay().resume();
230
+ this.menuProps = null;
231
+ this.updatePageDisplay();
232
+ }
233
+ catch (err) {
234
+ this.logError(err, 'onResume');
235
+ }
236
+ }
237
+ onStop() {
238
+ try {
239
+ this.getRideDisplay().stop(true);
240
+ this.emitNavigateBack();
241
+ }
242
+ catch (err) {
243
+ this.logError(err, 'onStop');
244
+ }
245
+ }
246
+ onStepBack() {
247
+ try {
248
+ this.getRideDisplay().backward();
249
+ }
250
+ catch (err) {
251
+ this.logError(err, 'onStepBack');
252
+ }
253
+ }
254
+ onStepForward() {
255
+ try {
256
+ this.getRideDisplay().forward();
257
+ }
258
+ catch (err) {
259
+ this.logError(err, 'onStepForward');
260
+ }
261
+ }
262
+ onIncreaseLoad() {
263
+ this.adjustLoad(DEFAULT_LOAD_INCREMENT);
264
+ }
265
+ onDecreaseLoad() {
266
+ this.adjustLoad(-DEFAULT_LOAD_INCREMENT);
267
+ }
268
+ onRetryStart() {
269
+ try {
270
+ this.getRideDisplay().retryStart();
271
+ }
272
+ catch (err) {
273
+ this.logError(err, 'onRetryStart');
274
+ }
275
+ }
276
+ onIgnoreStart() {
277
+ try {
278
+ this.getRideDisplay().startWithMissingSensors();
279
+ }
280
+ catch (err) {
281
+ this.logError(err, 'onIgnoreStart');
282
+ }
283
+ }
284
+ onCancelStart() {
285
+ try {
286
+ this.rideObserver?.stop();
287
+ this.getRideDisplay().cancelStart()
288
+ .then(() => {
289
+ this.moveToPreviousPage();
290
+ this.closePage();
291
+ })
292
+ .catch((err) => { this.logError(err, 'onCancelStart'); });
293
+ }
294
+ catch (err) {
295
+ this.logError(err, 'onCancelStart');
296
+ }
297
+ }
298
+ adjustLoad(deltaPct) {
299
+ try {
300
+ if (deltaPct >= 0)
301
+ this.getWorkoutRide().powerUp(deltaPct);
302
+ else
303
+ this.getWorkoutRide().powerDown(-deltaPct);
304
+ }
305
+ catch (err) {
306
+ this.logError(err, 'adjustLoad');
307
+ }
308
+ }
309
+ onRideStateUpdate(state) {
310
+ this.subscribeToWorkoutObserver();
311
+ switch (state) {
312
+ case 'Paused':
313
+ this.menuProps = { showResume: true, ...this.getStepFlags() };
314
+ this.updatePageDisplay();
315
+ break;
316
+ case 'Active':
317
+ this.menuProps = null;
318
+ this.updatePageDisplay();
319
+ break;
320
+ case 'Finished':
321
+ this.emitNavigateBack();
322
+ break;
323
+ case 'Error':
324
+ this.updatePageDisplay();
325
+ break;
326
+ }
327
+ }
328
+ onWorkoutUpdate() {
329
+ this.updatePageDisplay();
330
+ }
331
+ onWorkoutFinished() {
332
+ this.emitNavigateBack();
333
+ }
334
+ subscribeToWorkoutObserver() {
335
+ if (this.workoutObserverSubscribed)
336
+ return;
337
+ const observer = this.getWorkoutRide().getObserver();
338
+ if (!observer)
339
+ return;
340
+ Object.keys(this.workoutEventHandler).forEach(event => observer.on(event, this.workoutEventHandler[event]));
341
+ this.workoutObserverSubscribed = true;
342
+ }
343
+ unsubscribeFromWorkoutObserver() {
344
+ if (!this.workoutObserverSubscribed)
345
+ return;
346
+ const observer = this.getWorkoutRide().getObserver();
347
+ Object.keys(this.workoutEventHandler).forEach(event => observer?.off(event, this.workoutEventHandler[event]));
348
+ this.workoutObserverSubscribed = false;
349
+ }
350
+ registerRideEventHandlers() {
351
+ Object.keys(this.rideEventHandler).forEach(event => this.rideObserver?.on(event, this.rideEventHandler[event]));
352
+ }
353
+ unregisterRideEventHandlers() {
354
+ Object.keys(this.rideEventHandler).forEach(event => this.rideObserver?.off(event, this.rideEventHandler[event]));
355
+ }
356
+ buildBaseProps() {
357
+ const state = this.getRideDisplay().getState();
358
+ const isStarting = state === 'Idle' || state === 'Starting' || state === 'Error';
359
+ return {
360
+ rideState: state,
361
+ rideType: this.getRideDisplay().getRideType(),
362
+ startOverlayProps: isStarting ? this.getRideDisplay().getStartOverlayProps() : null,
363
+ menuProps: this.menuProps,
364
+ startGateProps: null
365
+ };
366
+ }
367
+ buildGraphPlan(current, ftp) {
368
+ if (!current) {
369
+ return { bars: [], ftp: ftp ?? 0, ftpLine: ftp ?? 0, domain: { x: [0, 0], y: [0, 0] } };
370
+ }
371
+ const bars = getWorkoutGraphSeries(current, { ftp, absValues: true });
372
+ const lastBarX = bars.length ? bars.at(-1).x : 0;
373
+ const maxX = Math.max(this.getLastLogTime(), lastBarX, current.duration ?? 0);
374
+ const maxBarPower = bars.length ? Math.max(...bars.map(b => b.y)) : 0;
375
+ return {
376
+ bars,
377
+ ftp,
378
+ ftpLine: ftp,
379
+ domain: { x: [0, maxX], y: [0, maxBarPower * 1.1] }
380
+ };
381
+ }
382
+ buildUpcomingSteps(current, ftp) {
383
+ const empty = { previous: null, current: null, upcoming: [], hasMore: false };
384
+ if (!current)
385
+ return empty;
386
+ const limits = this.getWorkoutRide().getCurrentLimits();
387
+ if (!limits)
388
+ return empty;
389
+ const currentStep = {
390
+ label: getStepTargetText(limits.step ?? {}, ftp, { min: limits.minPower, max: limits.maxPower }),
391
+ targetPower: limits.targetPower ?? null,
392
+ duration: limits.duration,
393
+ remaining: limits.remaining,
394
+ isCurrent: true
395
+ };
396
+ const elapsedTime = this.getElapsedActivityTime();
397
+ const flattened = getFlattenedSteps(current);
398
+ const currentIndex = flattened.findIndex(s => s.start <= elapsedTime && s.end > elapsedTime);
399
+ const toDisplay = (entry) => ({
400
+ label: getStepTargetText(entry.step, ftp),
401
+ targetPower: this.getStepAbsolutePower(entry.step, ftp),
402
+ duration: entry.duration,
403
+ remaining: null,
404
+ isCurrent: false
405
+ });
406
+ if (currentIndex === -1)
407
+ return { previous: null, current: currentStep, upcoming: [], hasMore: false };
408
+ const previous = currentIndex > 0 ? toDisplay(flattened[currentIndex - 1]) : null;
409
+ const upcomingEntries = flattened.slice(currentIndex + 1, currentIndex + 1 + UPCOMING_STEPS_COUNT);
410
+ const upcoming = upcomingEntries.map(toDisplay);
411
+ const hasMore = currentIndex + 1 + UPCOMING_STEPS_COUNT < flattened.length;
412
+ return { previous, current: currentStep, upcoming, hasMore };
413
+ }
414
+ buildDashboardLine(wo) {
415
+ const limits = this.getWorkoutRide().getCurrentLimits();
416
+ const title = wo.title ?? '';
417
+ if (!limits)
418
+ return { text: title, mode: wo.mode ?? null };
419
+ const target = getStepTargetText(limits.step ?? {}, wo.ftp, { min: limits.minPower, max: limits.maxPower });
420
+ const duration = getStepDuration({ duration: limits.duration });
421
+ const text = title ? `${target} for ${duration} - ${title}` : `${target} for ${duration}`;
422
+ return { text, mode: wo.mode ?? null };
423
+ }
424
+ getStepAbsolutePower(step, ftp) {
425
+ const p = step.power;
426
+ if (!p)
427
+ return null;
428
+ const val = p.max ?? p.min;
429
+ if (val === undefined)
430
+ return null;
431
+ if (p.type === 'watt')
432
+ return Math.round(val);
433
+ if (ftp === undefined)
434
+ return null;
435
+ return Math.round(val / 100 * ftp);
436
+ }
437
+ getStepFlags() {
438
+ const wo = this.getWorkoutRide().getDashboardDisplayProperties();
439
+ return { canStepBack: !!wo.canShowBackward, canStepForward: !!wo.canShowForward };
440
+ }
441
+ getLastLogTime() {
442
+ const logs = this.getActivityRide().getActivity()?.logs;
443
+ if (!logs || logs.length === 0)
444
+ return 0;
445
+ return logs.at(-1).time ?? 0;
446
+ }
447
+ getElapsedActivityTime() {
448
+ return this.getActivityRide().getActivity()?.time ?? 0;
449
+ }
450
+ getEmptyDisplayProps() {
451
+ return {
452
+ rideState: 'Error',
453
+ rideType: null,
454
+ startOverlayProps: null,
455
+ menuProps: null,
456
+ startGateProps: null,
457
+ title: '',
458
+ graph: { bars: [], ftp: 0, ftpLine: 0, domain: { x: [0, 0], y: [0, 0] } },
459
+ steps: { previous: null, current: null, upcoming: [], hasMore: false },
460
+ dashboard: { text: '', mode: null }
461
+ };
462
+ }
463
+ updatePageDisplay() {
464
+ this.getPageObserver()?.emit('page-update');
465
+ }
466
+ emitNavigateBack() {
467
+ this.getPageObserver()?.emit('navigate-back');
468
+ }
469
+ moveToPreviousPage() {
470
+ this.moveTo('$contentPage');
471
+ }
472
+ get rideObserver() {
473
+ try {
474
+ return this.getRideDisplay()?.getObserver();
475
+ }
476
+ catch (err) {
477
+ this.logError(err, 'get rideObserver');
478
+ }
479
+ return null;
480
+ }
481
+ getRideDisplay() {
482
+ return useRideDisplay();
483
+ }
484
+ getWorkoutRide() {
485
+ return useWorkoutRide();
486
+ }
487
+ getActivityRide() {
488
+ return useActivityRide();
489
+ }
490
+ };
491
+ return WorkoutRidePageService = _classThis;
492
+ })();
493
+ export { WorkoutRidePageService };
494
+ export const getWorkoutRidePageService = () => new WorkoutRidePageService();
@@ -0,0 +1 @@
1
+ export {};
@@ -495,7 +495,7 @@ let WorkoutRide = (() => {
495
495
  request.maxCadence = limits?.cadence?.max ? Math.round(limits.cadence.max) : undefined;
496
496
  request.minHrm = limits.hrm?.min ? Math.round(limits.hrm.min) : undefined;
497
497
  request.maxHrm = limits.hrm?.max ? Math.round(limits.hrm.max) : undefined;
498
- this.currentLimits = { ...request, duration: limits.duration, remaining: limits.remaining };
498
+ this.currentLimits = { ...request, duration: limits.duration, remaining: limits.remaining, step: limits.step };
499
499
  }
500
500
  getZoomParameters(time) {
501
501
  let start, stop;
@@ -0,0 +1 @@
1
+ export {};
@@ -6,3 +6,4 @@ export type * from './activities/types';
6
6
  export type * from './ride/types';
7
7
  export type * from './settings/types';
8
8
  export type * from './apps/types';
9
+ export type * from './workouts/types';
@@ -0,0 +1,2 @@
1
+ export * from './series';
2
+ export * from './types';
@@ -0,0 +1,18 @@
1
+ import { Step, Workout } from "../model";
2
+ import { StepDefinition } from "../model/types";
3
+ import { WorkoutGraphPlanBar, WorkoutGraphSeriesOptions } from "./types";
4
+ export declare const WORKOUT_ZONE_COLORS: string[];
5
+ export declare function getStepDuration(step: StepDefinition): string;
6
+ export declare function getStepPower(step: StepDefinition, ftp?: number): string;
7
+ export declare function getStepTargetText(step: StepDefinition, ftp?: number, powerOverrideWatts?: {
8
+ min?: number;
9
+ max?: number;
10
+ }): string;
11
+ export interface FlattenedStep {
12
+ step: Step;
13
+ start: number;
14
+ end: number;
15
+ duration: number;
16
+ }
17
+ export declare function getFlattenedSteps(workout: Workout): FlattenedStep[];
18
+ export declare function getWorkoutGraphSeries(workout: Workout, opts?: WorkoutGraphSeriesOptions): WorkoutGraphPlanBar[];
@@ -0,0 +1,11 @@
1
+ export interface WorkoutGraphPlanBar {
2
+ x0: number;
3
+ x: number;
4
+ y: number;
5
+ y0: number;
6
+ zone: number;
7
+ }
8
+ export interface WorkoutGraphSeriesOptions {
9
+ ftp?: number;
10
+ absValues?: boolean;
11
+ }
@@ -1,4 +1,3 @@
1
1
  export * from './Workout';
2
2
  export * from './Segment';
3
3
  export * from './Step';
4
- export * from './types';
@@ -1,7 +1,8 @@
1
1
  import { EventLogger } from "gd-eventlog";
2
2
  import { WorkoutParser } from "../types";
3
3
  import { FileInfo } from "../../../../api";
4
- import { Limit, PowerLimit, SegmentDefinition, StepDefinition, Workout } from "../../model";
4
+ import { Workout } from "../../model";
5
+ import { Limit, PowerLimit, SegmentDefinition, StepDefinition } from "../../model/types";
5
6
  import { IntervalsStep, IntervalsValue, IntervalsWorkout } from "./types";
6
7
  export declare class IntervalsJsonParser implements WorkoutParser<string | IntervalsWorkout> {
7
8
  protected logger: EventLogger;
@@ -23,6 +23,7 @@ export declare class WorkoutCalendarService extends IncyclistService {
23
23
  reset(): void;
24
24
  isInitialized(): boolean;
25
25
  getScheduledWorkouts(): Array<ScheduledWorkout>;
26
+ getScheduledToday(): ScheduledWorkout | undefined;
26
27
  setActive(active: boolean): void;
27
28
  onAppConnected(app: string, success?: boolean): void;
28
29
  onAppDisconnected(app: string): void;
@@ -1,3 +1,5 @@
1
1
  export * from './list';
2
2
  export * from './ride';
3
3
  export * from './base/model';
4
+ export * from './base/graph';
5
+ export * from './page';
@@ -1,4 +1,3 @@
1
1
  export * from './WorkoutCreateCard';
2
2
  export * from './WorkoutImportCard';
3
3
  export * from './WorkoutCard';
4
- export * from './types';
@@ -1,3 +1,2 @@
1
1
  export * from './service';
2
2
  export * from './cards';
3
- export * from './pageService';