incyclist-services 1.7.80 → 1.7.82

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.
@@ -389,6 +389,13 @@ let RouteCard = (() => {
389
389
  showNextOverwrite = false;
390
390
  }
391
391
  }
392
+ if (showNextOverwrite) {
393
+ const nextVideoEnabled = this.isMobile() ? this.getAppState().hasFeature('MOBILE_NEXT_VIDEO') : true;
394
+ if (!nextVideoEnabled) {
395
+ showNextOverwrite = false;
396
+ uiSettings.nextOverwrite = true;
397
+ }
398
+ }
392
399
  }
393
400
  catch (err) {
394
401
  this.logError(err, 'openSettings');
@@ -540,6 +547,7 @@ let RouteCard = (() => {
540
547
  start() {
541
548
  try {
542
549
  const service = (0, service_1.getRouteList)();
550
+ this.enforceNextVideoOverrideOnMobile();
543
551
  service.select(this.route);
544
552
  service.setStartSettings({ type: this.getCardType(), ...this.startSettings });
545
553
  this.route.description.tsLastStart = Date.now();
@@ -556,6 +564,7 @@ let RouteCard = (() => {
556
564
  addWorkout() {
557
565
  try {
558
566
  const service = (0, service_1.getRouteList)();
567
+ this.enforceNextVideoOverrideOnMobile();
559
568
  service.select(this.route);
560
569
  service.setStartSettings({ type: this.getCardType(), ...this.startSettings });
561
570
  this.route.description.tsLastStart = Date.now();
@@ -565,6 +574,21 @@ let RouteCard = (() => {
565
574
  this.logError(err, 'addWorkout');
566
575
  }
567
576
  }
577
+ enforceNextVideoOverrideOnMobile() {
578
+ try {
579
+ if (!this.isMobile())
580
+ return;
581
+ if (!this.startSettings || !(0, route_1.hasNextVideo)(this.route))
582
+ return;
583
+ const nextVideoEnabled = this.getAppState().hasFeature('MOBILE_NEXT_VIDEO');
584
+ if (!nextVideoEnabled) {
585
+ this.startSettings.nextOverwrite = true;
586
+ }
587
+ }
588
+ catch (err) {
589
+ this.logError(err, 'enforceNextVideoOverrideOnMobile');
590
+ }
591
+ }
568
592
  getCurrentDownload() {
569
593
  return this.downloadObserver;
570
594
  }
@@ -11,11 +11,12 @@ class Workout extends Segment_1.Segment {
11
11
  name;
12
12
  description;
13
13
  category;
14
+ explicitId;
14
15
  constructor(opts) {
15
16
  super(opts, true);
16
17
  this.name = opts.name || '';
17
18
  this._hash = opts.hash;
18
- this.id = opts.id || this.hash;
19
+ this.explicitId = !!(opts.id || opts.hash);
19
20
  this.description = opts.description || undefined;
20
21
  this.repeat = 1;
21
22
  this.type = 'workout';
@@ -32,6 +33,7 @@ class Workout extends Segment_1.Segment {
32
33
  catch {
33
34
  }
34
35
  });
36
+ this.id = opts.id || this.hash;
35
37
  }
36
38
  get hash() {
37
39
  if (this._hash)
@@ -41,6 +43,12 @@ class Workout extends Segment_1.Segment {
41
43
  this._hash = crypto.createHash('md5').update(JSON.stringify({ name, description, steps, repeat })).digest('hex');
42
44
  return this._hash;
43
45
  }
46
+ refreshHash() {
47
+ if (this.explicitId)
48
+ return;
49
+ this._hash = undefined;
50
+ this.id = this.hash;
51
+ }
44
52
  getSegment(time) {
45
53
  const s = this.steps.find(s => s.getStart() <= time && s.getEnd() > time);
46
54
  if (s?.type === 'segment')
@@ -57,6 +65,7 @@ class Workout extends Segment_1.Segment {
57
65
  const s = new Step_1.Step(step);
58
66
  this.push(s);
59
67
  }
68
+ this.refreshHash();
60
69
  }
61
70
  }
62
71
  addSegment(segment) {
@@ -68,6 +77,7 @@ class Workout extends Segment_1.Segment {
68
77
  const s = new Segment_1.Segment(segment);
69
78
  this.push(s);
70
79
  }
80
+ this.refreshHash();
71
81
  }
72
82
  }
73
83
  }
@@ -84,10 +94,10 @@ class Plan {
84
94
  this.type = 'plan';
85
95
  const { id, name, description, workouts, hash } = plan;
86
96
  this._hash = hash;
87
- this.id = id || this.hash;
88
97
  this.name = name;
89
98
  this.description = description;
90
99
  this.workouts = workouts;
100
+ this.id = id || this.hash;
91
101
  }
92
102
  get hash() {
93
103
  if (this._hash)
@@ -145,6 +145,10 @@ let WorkoutListService = (() => {
145
145
  }
146
146
  close() {
147
147
  this.getWorkoutCalendar().setActive(false);
148
+ this.logEvent({ message: 'close workout list' });
149
+ this.emit('closed', this.observer);
150
+ this.observer?.emit('stopped');
151
+ this.observer?.reset();
148
152
  }
149
153
  openSettings() {
150
154
  let workouts;
@@ -575,7 +579,7 @@ let WorkoutListService = (() => {
575
579
  return;
576
580
  const card = list.getCards().find(c => c.getData()?.id === id);
577
581
  if (card)
578
- res = { card, list: this.myWorkouts };
582
+ res = { card, list };
579
583
  });
580
584
  return res;
581
585
  }
@@ -596,11 +600,11 @@ let WorkoutListService = (() => {
596
600
  const workout = await this.parse(info);
597
601
  const existing = this.findCard(workout);
598
602
  if (existing) {
599
- existing.list.remove(existing.card);
600
- }
601
- else {
602
- this.items.push(workout);
603
+ const card = existing.card;
604
+ card.update(workout);
605
+ return card;
603
606
  }
607
+ this.items.push(workout);
604
608
  const card = new WorkoutCard_1.WorkoutCard(workout, { list: this.myWorkouts });
605
609
  card.save();
606
610
  card.enableDelete(true);
@@ -43,6 +43,7 @@ const observer_1 = require("../../base/types/observer");
43
43
  const settings_1 = require("../../settings");
44
44
  const calendar_1 = require("../calendar");
45
45
  const service_1 = require("../list/service");
46
+ const devices_1 = require("../../devices");
46
47
  const DEFAULT_IMPORT_GROUP = 'My Workouts';
47
48
  const UPCOMING_COLLAPSED_COUNT = 3;
48
49
  let WorkoutListPageService = (() => {
@@ -52,6 +53,7 @@ let WorkoutListPageService = (() => {
52
53
  let _classThis;
53
54
  let _classSuper = pages_1.IncyclistPageService;
54
55
  let _instanceExtraInitializers = [];
56
+ let _getDevicePairing_decorators;
55
57
  let _getWorkoutList_decorators;
56
58
  let _getWorkoutCalendar_decorators;
57
59
  let _getUserSettings_decorators;
@@ -60,10 +62,12 @@ let WorkoutListPageService = (() => {
60
62
  static { _classThis = this; }
61
63
  static {
62
64
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
65
+ _getDevicePairing_decorators = [decorators_1.Injectable];
63
66
  _getWorkoutList_decorators = [decorators_1.Injectable];
64
67
  _getWorkoutCalendar_decorators = [decorators_1.Injectable];
65
68
  _getUserSettings_decorators = [decorators_1.Injectable];
66
69
  _getAppState_decorators = [decorators_1.Injectable];
70
+ __esDecorate(this, null, _getDevicePairing_decorators, { kind: "method", name: "getDevicePairing", static: false, private: false, access: { has: obj => "getDevicePairing" in obj, get: obj => obj.getDevicePairing }, metadata: _metadata }, null, _instanceExtraInitializers);
67
71
  __esDecorate(this, null, _getWorkoutList_decorators, { kind: "method", name: "getWorkoutList", static: false, private: false, access: { has: obj => "getWorkoutList" in obj, get: obj => obj.getWorkoutList }, metadata: _metadata }, null, _instanceExtraInitializers);
68
72
  __esDecorate(this, null, _getWorkoutCalendar_decorators, { kind: "method", name: "getWorkoutCalendar", static: false, private: false, access: { has: obj => "getWorkoutCalendar" in obj, get: obj => obj.getWorkoutCalendar }, metadata: _metadata }, null, _instanceExtraInitializers);
69
73
  __esDecorate(this, null, _getUserSettings_decorators, { kind: "method", name: "getUserSettings", static: false, private: false, access: { has: obj => "getUserSettings" in obj, get: obj => obj.getUserSettings }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -264,9 +268,15 @@ let WorkoutListPageService = (() => {
264
268
  const card = this.findWorkoutCard(id);
265
269
  if (!card)
266
270
  return;
267
- const settings = this.getWorkoutList().getStartSettings();
271
+ const service = this.getWorkoutList();
272
+ const pairing = this.getDevicePairing();
273
+ const settings = service.getStartSettings() ?? {};
268
274
  card.select({ ...settings, noRoute: opts?.noRoute });
269
- this.getPageObserver()?.emit('start-ride', { id, noRoute: opts?.noRoute });
275
+ this.logEvent({ message: 'Attempting to start a ride', id, ...settings, noRoute: opts?.noRoute, readyToStart: pairing.isReadyToStart(), });
276
+ this.detailWorkoutId = null;
277
+ service.close();
278
+ const next = pairing.isReadyToStart() ? '/rideDeviceOK' : '/pairingStart';
279
+ this.moveTo(next);
270
280
  }
271
281
  catch (err) {
272
282
  this.logError(err, 'onStart');
@@ -314,6 +324,8 @@ let WorkoutListPageService = (() => {
314
324
  this.getWorkoutList().import(file, { showImportCards: false })
315
325
  .then(([card]) => {
316
326
  const group = this.getLastUsedImportGroup();
327
+ if (group !== DEFAULT_IMPORT_GROUP)
328
+ card.move(group);
317
329
  this.importPhase = 'result';
318
330
  this.importResult = { id: card.getId(), workoutName: card.getTitle(), group };
319
331
  observer.emit('success');
@@ -364,7 +376,7 @@ let WorkoutListPageService = (() => {
364
376
  const todayId = calendar.getScheduledToday()?.id ?? null;
365
377
  const selectedWorkout = this.getWorkoutList().getSelected();
366
378
  const items = scheduled.map(w => ({
367
- id: w.id,
379
+ id: w.workout?.id,
368
380
  title: w.workout?.name,
369
381
  date: w.day,
370
382
  duration: this.formatDuration(w.workout?.duration),
@@ -446,7 +458,15 @@ let WorkoutListPageService = (() => {
446
458
  this.getPageObserver()?.emit('page-update');
447
459
  }
448
460
  emitImportUpdate() {
449
- this.getPageObserver()?.emit('import-update');
461
+ try {
462
+ this.getPageObserver()?.emit('import-update');
463
+ }
464
+ catch (err) {
465
+ this.logError(err, 'emitImportUpdate');
466
+ }
467
+ }
468
+ getDevicePairing() {
469
+ return (0, devices_1.useDevicePairing)();
450
470
  }
451
471
  getWorkoutList() {
452
472
  return (0, service_1.useWorkoutList)();
@@ -77,7 +77,6 @@ let WorkoutRidePageService = (() => {
77
77
  backgroundTimer;
78
78
  backgroundPausedByService = false;
79
79
  menuProps = null;
80
- isInitialized = false;
81
80
  constructor() {
82
81
  super('WorkoutRidePage');
83
82
  this.rideEventHandler['state-update'] = this.onRideStateUpdate.bind(this);
@@ -95,10 +94,6 @@ let WorkoutRidePageService = (() => {
95
94
  super.openPage();
96
95
  try {
97
96
  const service = this.getRideDisplay();
98
- if (!this.isInitialized) {
99
- service.init();
100
- this.isInitialized = true;
101
- }
102
97
  this.registerRideEventHandlers();
103
98
  this.subscribeToWorkoutObserver();
104
99
  service.start(simulate);
@@ -120,7 +115,6 @@ let WorkoutRidePageService = (() => {
120
115
  this.unregisterRideEventHandlers();
121
116
  this.unsubscribeFromWorkoutObserver();
122
117
  this.menuProps = null;
123
- this.isInitialized = false;
124
118
  super.closePage();
125
119
  }
126
120
  catch (err) {
@@ -314,19 +308,15 @@ let WorkoutRidePageService = (() => {
314
308
  switch (state) {
315
309
  case 'Paused':
316
310
  this.menuProps = { showResume: true, ...this.getStepFlags() };
317
- this.updatePageDisplay();
318
311
  break;
319
312
  case 'Active':
320
313
  this.menuProps = null;
321
- this.updatePageDisplay();
322
314
  break;
323
315
  case 'Finished':
324
316
  this.emitNavigateBack();
325
- break;
326
- case 'Error':
327
- this.updatePageDisplay();
328
- break;
317
+ return;
329
318
  }
319
+ this.updatePageDisplay();
330
320
  }
331
321
  onWorkoutUpdate() {
332
322
  this.updatePageDisplay();
@@ -373,7 +363,8 @@ let WorkoutRidePageService = (() => {
373
363
  }
374
364
  const bars = (0, graph_1.getWorkoutGraphSeries)(current, { ftp, absValues: true });
375
365
  const lastBarX = bars.length ? bars.at(-1).x : 0;
376
- const maxX = Math.max(this.getLastLogTime(), lastBarX, current.duration ?? 0);
366
+ const maxXCandidates = [this.getLastLogTime(), lastBarX, current.duration ?? 0].filter(Number.isFinite);
367
+ const maxX = maxXCandidates.length ? Math.max(...maxXCandidates) : 0;
377
368
  const maxBarPower = bars.length ? Math.max(...bars.map(b => b.y)) : 0;
378
369
  return {
379
370
  bars,
@@ -43,7 +43,7 @@ import { valid } from "../../../utils/valid";
43
43
  import { waitNextTick } from "../../../utils";
44
44
  import { useRouteDownload } from "../../download/service";
45
45
  import { EventLogger } from "gd-eventlog";
46
- import { checkIsLoop, getNextVideoId, getPosition, updateSlopes } from "../../base/utils/route";
46
+ import { checkIsLoop, getNextVideoId, hasNextVideo, getPosition, updateSlopes } from "../../base/utils/route";
47
47
  import { getWorkoutList } from "../../../workouts";
48
48
  import { checkIsNew } from "../utils";
49
49
  import { useOnlineStatusMonitoring } from "../../../monitoring";
@@ -386,6 +386,13 @@ let RouteCard = (() => {
386
386
  showNextOverwrite = false;
387
387
  }
388
388
  }
389
+ if (showNextOverwrite) {
390
+ const nextVideoEnabled = this.isMobile() ? this.getAppState().hasFeature('MOBILE_NEXT_VIDEO') : true;
391
+ if (!nextVideoEnabled) {
392
+ showNextOverwrite = false;
393
+ uiSettings.nextOverwrite = true;
394
+ }
395
+ }
389
396
  }
390
397
  catch (err) {
391
398
  this.logError(err, 'openSettings');
@@ -537,6 +544,7 @@ let RouteCard = (() => {
537
544
  start() {
538
545
  try {
539
546
  const service = getRouteList();
547
+ this.enforceNextVideoOverrideOnMobile();
540
548
  service.select(this.route);
541
549
  service.setStartSettings({ type: this.getCardType(), ...this.startSettings });
542
550
  this.route.description.tsLastStart = Date.now();
@@ -553,6 +561,7 @@ let RouteCard = (() => {
553
561
  addWorkout() {
554
562
  try {
555
563
  const service = getRouteList();
564
+ this.enforceNextVideoOverrideOnMobile();
556
565
  service.select(this.route);
557
566
  service.setStartSettings({ type: this.getCardType(), ...this.startSettings });
558
567
  this.route.description.tsLastStart = Date.now();
@@ -562,6 +571,21 @@ let RouteCard = (() => {
562
571
  this.logError(err, 'addWorkout');
563
572
  }
564
573
  }
574
+ enforceNextVideoOverrideOnMobile() {
575
+ try {
576
+ if (!this.isMobile())
577
+ return;
578
+ if (!this.startSettings || !hasNextVideo(this.route))
579
+ return;
580
+ const nextVideoEnabled = this.getAppState().hasFeature('MOBILE_NEXT_VIDEO');
581
+ if (!nextVideoEnabled) {
582
+ this.startSettings.nextOverwrite = true;
583
+ }
584
+ }
585
+ catch (err) {
586
+ this.logError(err, 'enforceNextVideoOverrideOnMobile');
587
+ }
588
+ }
565
589
  getCurrentDownload() {
566
590
  return this.downloadObserver;
567
591
  }
@@ -8,11 +8,12 @@ export class Workout extends Segment {
8
8
  name;
9
9
  description;
10
10
  category;
11
+ explicitId;
11
12
  constructor(opts) {
12
13
  super(opts, true);
13
14
  this.name = opts.name || '';
14
15
  this._hash = opts.hash;
15
- this.id = opts.id || this.hash;
16
+ this.explicitId = !!(opts.id || opts.hash);
16
17
  this.description = opts.description || undefined;
17
18
  this.repeat = 1;
18
19
  this.type = 'workout';
@@ -29,6 +30,7 @@ export class Workout extends Segment {
29
30
  catch {
30
31
  }
31
32
  });
33
+ this.id = opts.id || this.hash;
32
34
  }
33
35
  get hash() {
34
36
  if (this._hash)
@@ -38,6 +40,12 @@ export class Workout extends Segment {
38
40
  this._hash = crypto.createHash('md5').update(JSON.stringify({ name, description, steps, repeat })).digest('hex');
39
41
  return this._hash;
40
42
  }
43
+ refreshHash() {
44
+ if (this.explicitId)
45
+ return;
46
+ this._hash = undefined;
47
+ this.id = this.hash;
48
+ }
41
49
  getSegment(time) {
42
50
  const s = this.steps.find(s => s.getStart() <= time && s.getEnd() > time);
43
51
  if (s?.type === 'segment')
@@ -54,6 +62,7 @@ export class Workout extends Segment {
54
62
  const s = new Step(step);
55
63
  this.push(s);
56
64
  }
65
+ this.refreshHash();
57
66
  }
58
67
  }
59
68
  addSegment(segment) {
@@ -65,6 +74,7 @@ export class Workout extends Segment {
65
74
  const s = new Segment(segment);
66
75
  this.push(s);
67
76
  }
77
+ this.refreshHash();
68
78
  }
69
79
  }
70
80
  }
@@ -80,10 +90,10 @@ export class Plan {
80
90
  this.type = 'plan';
81
91
  const { id, name, description, workouts, hash } = plan;
82
92
  this._hash = hash;
83
- this.id = id || this.hash;
84
93
  this.name = name;
85
94
  this.description = description;
86
95
  this.workouts = workouts;
96
+ this.id = id || this.hash;
87
97
  }
88
98
  get hash() {
89
99
  if (this._hash)
@@ -142,6 +142,10 @@ let WorkoutListService = (() => {
142
142
  }
143
143
  close() {
144
144
  this.getWorkoutCalendar().setActive(false);
145
+ this.logEvent({ message: 'close workout list' });
146
+ this.emit('closed', this.observer);
147
+ this.observer?.emit('stopped');
148
+ this.observer?.reset();
145
149
  }
146
150
  openSettings() {
147
151
  let workouts;
@@ -572,7 +576,7 @@ let WorkoutListService = (() => {
572
576
  return;
573
577
  const card = list.getCards().find(c => c.getData()?.id === id);
574
578
  if (card)
575
- res = { card, list: this.myWorkouts };
579
+ res = { card, list };
576
580
  });
577
581
  return res;
578
582
  }
@@ -593,11 +597,11 @@ let WorkoutListService = (() => {
593
597
  const workout = await this.parse(info);
594
598
  const existing = this.findCard(workout);
595
599
  if (existing) {
596
- existing.list.remove(existing.card);
597
- }
598
- else {
599
- this.items.push(workout);
600
+ const card = existing.card;
601
+ card.update(workout);
602
+ return card;
600
603
  }
604
+ this.items.push(workout);
601
605
  const card = new WorkoutCard(workout, { list: this.myWorkouts });
602
606
  card.save();
603
607
  card.enableDelete(true);
@@ -40,6 +40,7 @@ import { Observer } from "../../base/types/observer";
40
40
  import { useUserSettings } from "../../settings";
41
41
  import { useWorkoutCalendar } from "../calendar";
42
42
  import { useWorkoutList } from "../list/service";
43
+ import { useDevicePairing } from "../../devices";
43
44
  const DEFAULT_IMPORT_GROUP = 'My Workouts';
44
45
  const UPCOMING_COLLAPSED_COUNT = 3;
45
46
  let WorkoutListPageService = (() => {
@@ -49,6 +50,7 @@ let WorkoutListPageService = (() => {
49
50
  let _classThis;
50
51
  let _classSuper = IncyclistPageService;
51
52
  let _instanceExtraInitializers = [];
53
+ let _getDevicePairing_decorators;
52
54
  let _getWorkoutList_decorators;
53
55
  let _getWorkoutCalendar_decorators;
54
56
  let _getUserSettings_decorators;
@@ -57,10 +59,12 @@ let WorkoutListPageService = (() => {
57
59
  static { _classThis = this; }
58
60
  static {
59
61
  const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
62
+ _getDevicePairing_decorators = [Injectable];
60
63
  _getWorkoutList_decorators = [Injectable];
61
64
  _getWorkoutCalendar_decorators = [Injectable];
62
65
  _getUserSettings_decorators = [Injectable];
63
66
  _getAppState_decorators = [Injectable];
67
+ __esDecorate(this, null, _getDevicePairing_decorators, { kind: "method", name: "getDevicePairing", static: false, private: false, access: { has: obj => "getDevicePairing" in obj, get: obj => obj.getDevicePairing }, metadata: _metadata }, null, _instanceExtraInitializers);
64
68
  __esDecorate(this, null, _getWorkoutList_decorators, { kind: "method", name: "getWorkoutList", static: false, private: false, access: { has: obj => "getWorkoutList" in obj, get: obj => obj.getWorkoutList }, metadata: _metadata }, null, _instanceExtraInitializers);
65
69
  __esDecorate(this, null, _getWorkoutCalendar_decorators, { kind: "method", name: "getWorkoutCalendar", static: false, private: false, access: { has: obj => "getWorkoutCalendar" in obj, get: obj => obj.getWorkoutCalendar }, metadata: _metadata }, null, _instanceExtraInitializers);
66
70
  __esDecorate(this, null, _getUserSettings_decorators, { kind: "method", name: "getUserSettings", static: false, private: false, access: { has: obj => "getUserSettings" in obj, get: obj => obj.getUserSettings }, metadata: _metadata }, null, _instanceExtraInitializers);
@@ -261,9 +265,15 @@ let WorkoutListPageService = (() => {
261
265
  const card = this.findWorkoutCard(id);
262
266
  if (!card)
263
267
  return;
264
- const settings = this.getWorkoutList().getStartSettings();
268
+ const service = this.getWorkoutList();
269
+ const pairing = this.getDevicePairing();
270
+ const settings = service.getStartSettings() ?? {};
265
271
  card.select({ ...settings, noRoute: opts?.noRoute });
266
- this.getPageObserver()?.emit('start-ride', { id, noRoute: opts?.noRoute });
272
+ this.logEvent({ message: 'Attempting to start a ride', id, ...settings, noRoute: opts?.noRoute, readyToStart: pairing.isReadyToStart(), });
273
+ this.detailWorkoutId = null;
274
+ service.close();
275
+ const next = pairing.isReadyToStart() ? '/rideDeviceOK' : '/pairingStart';
276
+ this.moveTo(next);
267
277
  }
268
278
  catch (err) {
269
279
  this.logError(err, 'onStart');
@@ -311,6 +321,8 @@ let WorkoutListPageService = (() => {
311
321
  this.getWorkoutList().import(file, { showImportCards: false })
312
322
  .then(([card]) => {
313
323
  const group = this.getLastUsedImportGroup();
324
+ if (group !== DEFAULT_IMPORT_GROUP)
325
+ card.move(group);
314
326
  this.importPhase = 'result';
315
327
  this.importResult = { id: card.getId(), workoutName: card.getTitle(), group };
316
328
  observer.emit('success');
@@ -361,7 +373,7 @@ let WorkoutListPageService = (() => {
361
373
  const todayId = calendar.getScheduledToday()?.id ?? null;
362
374
  const selectedWorkout = this.getWorkoutList().getSelected();
363
375
  const items = scheduled.map(w => ({
364
- id: w.id,
376
+ id: w.workout?.id,
365
377
  title: w.workout?.name,
366
378
  date: w.day,
367
379
  duration: this.formatDuration(w.workout?.duration),
@@ -443,7 +455,15 @@ let WorkoutListPageService = (() => {
443
455
  this.getPageObserver()?.emit('page-update');
444
456
  }
445
457
  emitImportUpdate() {
446
- this.getPageObserver()?.emit('import-update');
458
+ try {
459
+ this.getPageObserver()?.emit('import-update');
460
+ }
461
+ catch (err) {
462
+ this.logError(err, 'emitImportUpdate');
463
+ }
464
+ }
465
+ getDevicePairing() {
466
+ return useDevicePairing();
447
467
  }
448
468
  getWorkoutList() {
449
469
  return useWorkoutList();
@@ -74,7 +74,6 @@ let WorkoutRidePageService = (() => {
74
74
  backgroundTimer;
75
75
  backgroundPausedByService = false;
76
76
  menuProps = null;
77
- isInitialized = false;
78
77
  constructor() {
79
78
  super('WorkoutRidePage');
80
79
  this.rideEventHandler['state-update'] = this.onRideStateUpdate.bind(this);
@@ -92,10 +91,6 @@ let WorkoutRidePageService = (() => {
92
91
  super.openPage();
93
92
  try {
94
93
  const service = this.getRideDisplay();
95
- if (!this.isInitialized) {
96
- service.init();
97
- this.isInitialized = true;
98
- }
99
94
  this.registerRideEventHandlers();
100
95
  this.subscribeToWorkoutObserver();
101
96
  service.start(simulate);
@@ -117,7 +112,6 @@ let WorkoutRidePageService = (() => {
117
112
  this.unregisterRideEventHandlers();
118
113
  this.unsubscribeFromWorkoutObserver();
119
114
  this.menuProps = null;
120
- this.isInitialized = false;
121
115
  super.closePage();
122
116
  }
123
117
  catch (err) {
@@ -311,19 +305,15 @@ let WorkoutRidePageService = (() => {
311
305
  switch (state) {
312
306
  case 'Paused':
313
307
  this.menuProps = { showResume: true, ...this.getStepFlags() };
314
- this.updatePageDisplay();
315
308
  break;
316
309
  case 'Active':
317
310
  this.menuProps = null;
318
- this.updatePageDisplay();
319
311
  break;
320
312
  case 'Finished':
321
313
  this.emitNavigateBack();
322
- break;
323
- case 'Error':
324
- this.updatePageDisplay();
325
- break;
314
+ return;
326
315
  }
316
+ this.updatePageDisplay();
327
317
  }
328
318
  onWorkoutUpdate() {
329
319
  this.updatePageDisplay();
@@ -370,7 +360,8 @@ let WorkoutRidePageService = (() => {
370
360
  }
371
361
  const bars = getWorkoutGraphSeries(current, { ftp, absValues: true });
372
362
  const lastBarX = bars.length ? bars.at(-1).x : 0;
373
- const maxX = Math.max(this.getLastLogTime(), lastBarX, current.duration ?? 0);
363
+ const maxXCandidates = [this.getLastLogTime(), lastBarX, current.duration ?? 0].filter(Number.isFinite);
364
+ const maxX = maxXCandidates.length ? Math.max(...maxXCandidates) : 0;
374
365
  const maxBarPower = bars.length ? Math.max(...bars.map(b => b.y)) : 0;
375
366
  return {
376
367
  bars,
@@ -1,4 +1,4 @@
1
- export type FeatureToggle = 'NEW_SEARCH_UI' | 'CONTROLLERS' | 'MOBILE_WORKOUTS' | 'WEBBLE_WINDOWS';
1
+ export type FeatureToggle = 'NEW_SEARCH_UI' | 'CONTROLLERS' | 'MOBILE_WORKOUTS' | 'WEBBLE_WINDOWS' | 'MOBILE_NEXT_VIDEO';
2
2
  export type Interfaces = 'ant' | 'ble' | 'serial' | 'wifi' | 'tcpip';
3
3
  export type BLEFeatures = {
4
4
  services: Array<string>;
@@ -78,6 +78,7 @@ export declare class RouteCard extends BaseCard implements Card<Route> {
78
78
  start(): void;
79
79
  cancel(): void;
80
80
  addWorkout(): void;
81
+ protected enforceNextVideoOverrideOnMobile(): void;
81
82
  getCurrentDownload(): Observer;
82
83
  getVideoDir(): string;
83
84
  setVideoDir(dir: string): void;
@@ -6,8 +6,10 @@ export declare class Workout extends Segment implements WorkoutDefinition {
6
6
  name: string;
7
7
  description: string;
8
8
  category?: Category;
9
+ protected explicitId: boolean;
9
10
  constructor(opts: WorkoutDefinition);
10
11
  get hash(): string;
12
+ protected refreshHash(): void;
11
13
  getSegment(time: number): Segment;
12
14
  addStep(step: StepDefinition): void;
13
15
  addSegment(segment: SegmentDefinition): void;
@@ -50,6 +50,7 @@ export declare class WorkoutListPageService extends IncyclistPageService impleme
50
50
  protected formatDuration(duration: number): string;
51
51
  protected emitPageUpdate(): void;
52
52
  protected emitImportUpdate(): void;
53
+ protected getDevicePairing(): import("../../devices").DevicePairingService;
53
54
  protected getWorkoutList(): WorkoutListService;
54
55
  protected getWorkoutCalendar(): import("../calendar").WorkoutCalendarService;
55
56
  protected getUserSettings(): import("../../settings").UserSettingsService;
@@ -12,7 +12,6 @@ export declare class WorkoutRidePageService extends IncyclistPageService impleme
12
12
  protected backgroundTimer: NodeJS.Timeout | undefined;
13
13
  protected backgroundPausedByService: boolean;
14
14
  protected menuProps: WorkoutRideMenuProps | null;
15
- protected isInitialized: boolean;
16
15
  constructor();
17
16
  openPage(simulate?: boolean): IObserver;
18
17
  closePage(): void;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.7.80",
3
+ "version": "1.7.82",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.27"
6
6
  },