incyclist-services 1.7.119 → 1.7.120

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.
@@ -47,6 +47,7 @@ const Injection_1 = require("../../../base/decorators/Injection");
47
47
  const i18n_1 = require("../../../i18n");
48
48
  exports.DB_VERSION = '5';
49
49
  exports.DB_NAME = 'db';
50
+ const SHORT_RIDE_FILTER_CUTOFF = new Date('2026-08-28').getTime();
50
51
  let ActivitiesRepository = (() => {
51
52
  let _classDecorators = [types_1.Singleton];
52
53
  let _classDescriptor;
@@ -109,7 +110,7 @@ let ActivitiesRepository = (() => {
109
110
  this.write();
110
111
  }
111
112
  if (writeDetails) {
112
- this.writeDetails(activity);
113
+ await this.writeDetails(activity);
113
114
  }
114
115
  }
115
116
  migrate(activity, writeSummary = true) {
@@ -224,6 +225,16 @@ let ActivitiesRepository = (() => {
224
225
  }
225
226
  search(criteria) {
226
227
  let result = this.activities;
228
+ if (!this.isMobile()) {
229
+ result = result?.filter(ai => {
230
+ const { rideTime, startTime } = ai.summary;
231
+ if (rideTime < 1)
232
+ return false;
233
+ if (rideTime <= 30 && startTime < SHORT_RIDE_FILTER_CUTOFF)
234
+ return false;
235
+ return true;
236
+ });
237
+ }
227
238
  result = this.checkIdFilter(result, criteria);
228
239
  result = this.checkHashFilter(result, criteria);
229
240
  result = this.checkStartPosFilter(result, criteria);
@@ -475,7 +486,7 @@ let ActivitiesRepository = (() => {
475
486
  }
476
487
  async writeDetails(activity) {
477
488
  const name = activity.summary.name;
478
- this.getRepo().write(name, activity.details);
489
+ await this.getRepo().write(name, activity.details);
479
490
  }
480
491
  async scanForNewActivities() {
481
492
  try {
@@ -509,6 +520,13 @@ let ActivitiesRepository = (() => {
509
520
  getRouteList() {
510
521
  return (0, routes_1.useRouteList)();
511
522
  }
523
+ isMobile() {
524
+ const { appInfo } = this.getBindings();
525
+ if (!appInfo) {
526
+ return false;
527
+ }
528
+ return appInfo?.getChannel() === 'mobile';
529
+ }
512
530
  getBindings() {
513
531
  return (0, api_1.getBindings)();
514
532
  }
@@ -254,7 +254,7 @@ let Activity = (() => {
254
254
  isRouteAvailable() {
255
255
  if (!this.details?.route)
256
256
  return false;
257
- if (this.details.routeType === 'Free-Ride')
257
+ if (this.details.routeType === 'Free-Ride' || this.details.routeType === 'None')
258
258
  return false;
259
259
  return this.getRouteList().getRouteDescription(this.details.route.id) !== undefined;
260
260
  }
@@ -277,7 +277,7 @@ let Activity = (() => {
277
277
  canStart() {
278
278
  if (!this.details?.route)
279
279
  return false;
280
- if (this.details.routeType === 'Free-Ride')
280
+ if (this.details.routeType === 'Free-Ride' || this.details.routeType === 'None')
281
281
  return false;
282
282
  if (this.details.routeType === 'Video') {
283
283
  const isOnline = this.getOnlineMonitoring().onlineStatus;
@@ -198,7 +198,7 @@ let ActivityRideService = (() => {
198
198
  this.disableDeviceHealthCheck();
199
199
  this.state = 'completed';
200
200
  this.updateActivityTime();
201
- this._save();
201
+ await this._save();
202
202
  this.emit('completed');
203
203
  this.tsPauseStart = undefined;
204
204
  delete this.tsStart;
@@ -536,7 +536,7 @@ let ActivityRideService = (() => {
536
536
  if (this.state !== 'completed') {
537
537
  await this.stop();
538
538
  }
539
- this.getRepo().delete(this.activity.id);
539
+ await this.getRepo().delete(this.activity.id);
540
540
  this.state = 'idle';
541
541
  }
542
542
  save() {
@@ -552,7 +552,7 @@ let ActivityRideService = (() => {
552
552
  let success = false;
553
553
  try {
554
554
  emit('start', success);
555
- await this._save();
555
+ this._save();
556
556
  success = await this._convertAndUpload();
557
557
  (0, sleep_1.sleep)(0).then(() => {
558
558
  delete this.saveObserver;
@@ -965,7 +965,7 @@ let ActivityRideService = (() => {
965
965
  await fs.writeFile(fileName, Buffer.from(data));
966
966
  this.activity.tcxFileName = fileName;
967
967
  }
968
- await this._save();
968
+ this._save();
969
969
  emit('save.done', format, true);
970
970
  return true;
971
971
  }
@@ -22,8 +22,11 @@ function isVirtualShiftingEnabled(mode) {
22
22
  function getLoadButtonMode(mode) {
23
23
  if (!mode)
24
24
  return 'power';
25
- if (mode.isSIM() || mode.isResistance()) {
26
- return isVirtualShiftingEnabled(mode) ? 'gear' : 'hidden';
27
- }
28
- return 'power';
25
+ if (mode.isERG())
26
+ return 'power';
27
+ if (mode.isSIM() && isVirtualShiftingEnabled(mode))
28
+ return 'gear';
29
+ if (mode.isResistance())
30
+ return 'gear';
31
+ return 'hidden';
29
32
  }
@@ -39,6 +39,7 @@ const gd_eventlog_1 = require("gd-eventlog");
39
39
  const decorators_1 = require("../../base/decorators");
40
40
  const pages_1 = require("../../base/pages");
41
41
  const display_1 = require("../display");
42
+ const devices_1 = require("../../devices");
42
43
  const sleep_1 = require("../../utils/sleep");
43
44
  const monitoring_1 = require("../../monitoring");
44
45
  const activities_1 = require("../../activities");
@@ -64,6 +65,7 @@ let RidePageService = (() => {
64
65
  let _getActivityRide_decorators;
65
66
  let _getUserSettings_decorators;
66
67
  let _getOnlineStatusMonitoring_decorators;
68
+ let _getDeviceConfiguration_decorators;
67
69
  var RidePageService = class extends _classSuper {
68
70
  static { _classThis = this; }
69
71
  static {
@@ -73,11 +75,13 @@ let RidePageService = (() => {
73
75
  _getActivityRide_decorators = [decorators_1.Injectable];
74
76
  _getUserSettings_decorators = [decorators_1.Injectable];
75
77
  _getOnlineStatusMonitoring_decorators = [decorators_1.Injectable];
78
+ _getDeviceConfiguration_decorators = [decorators_1.Injectable];
76
79
  __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);
77
80
  __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);
78
81
  __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);
79
82
  __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);
80
83
  __esDecorate(this, null, _getOnlineStatusMonitoring_decorators, { kind: "method", name: "getOnlineStatusMonitoring", static: false, private: false, access: { has: obj => "getOnlineStatusMonitoring" in obj, get: obj => obj.getOnlineStatusMonitoring }, metadata: _metadata }, null, _instanceExtraInitializers);
84
+ __esDecorate(this, null, _getDeviceConfiguration_decorators, { kind: "method", name: "getDeviceConfiguration", static: false, private: false, access: { has: obj => "getDeviceConfiguration" in obj, get: obj => obj.getDeviceConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
81
85
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
82
86
  RidePageService = _classThis = _classDescriptor.value;
83
87
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
@@ -92,6 +96,7 @@ let RidePageService = (() => {
92
96
  menuProps = null;
93
97
  isInitialized = false;
94
98
  startGateProps = null;
99
+ onDeviceModeChangedBound = this.onDeviceModeChanged.bind(this);
95
100
  prevRidesVisibleRows = DEFAULT_PREV_RIDES_VISIBLE_ROWS;
96
101
  prevRidesMode = 'list';
97
102
  gestureHintDismissed = false;
@@ -143,6 +148,7 @@ let RidePageService = (() => {
143
148
  const registerAndStart = () => {
144
149
  this.registerHandlers(this.rideObserver, this.eventHandler);
145
150
  this.subscribeToWorkoutObserver();
151
+ this.getDeviceConfiguration().on('mode-changed', this.onDeviceModeChangedBound);
146
152
  const state = service.getState();
147
153
  if (state === 'Started' || state === 'Active' || state === 'Paused') {
148
154
  this.logError(new Error(`start() requested while ride is ${state}`), 'openPage');
@@ -187,6 +193,7 @@ let RidePageService = (() => {
187
193
  this.getRideDisplay().stop();
188
194
  this.unregisterHandlers(this.rideObserver, this.eventHandler);
189
195
  this.unsubscribeFromWorkoutObserver();
196
+ this.getDeviceConfiguration().off('mode-changed', this.onDeviceModeChangedBound);
190
197
  this.menuProps = null;
191
198
  this.isInitialized = false;
192
199
  super.closePage();
@@ -278,9 +285,11 @@ let RidePageService = (() => {
278
285
  onMenuOpen() {
279
286
  try {
280
287
  const state = this.getRideDisplay().getState();
288
+ const loadControl = this.getLoadControlProps();
289
+ const showRideSettings = !this.isRideType('Workout');
281
290
  this.menuProps = this.isWorkoutAttached()
282
- ? { showResume: state === 'Paused', ...this.getStepFlags() }
283
- : { showResume: state === 'Paused' };
291
+ ? { showResume: state === 'Paused', ...this.getStepFlags(), loadControl, showRideSettings }
292
+ : { showResume: state === 'Paused', loadControl, showRideSettings };
284
293
  this.updatePageDisplay();
285
294
  }
286
295
  catch (err) {
@@ -397,7 +406,7 @@ let RidePageService = (() => {
397
406
  const available = this.getCornerWidgetStates();
398
407
  if (available.length <= 1)
399
408
  return undefined;
400
- const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
409
+ const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'workout');
401
410
  return available.includes(current) ? current : available[0];
402
411
  }
403
412
  catch (err) {
@@ -414,7 +423,7 @@ let RidePageService = (() => {
414
423
  onToggleCornerWidget() {
415
424
  try {
416
425
  const available = this.getCornerWidgetStates();
417
- const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
426
+ const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'workout');
418
427
  const next = available[(available.indexOf(current) + 1) % available.length];
419
428
  this.getUserSettings().set(CORNER_WIDGET_SETTING_KEY, next);
420
429
  this.updatePageDisplay();
@@ -583,8 +592,7 @@ let RidePageService = (() => {
583
592
  const plainErgAdjustment = !this.getWorkoutRide().inUse() && this.getLoadButtonMode() === 'power';
584
593
  if (plainErgAdjustment) {
585
594
  const sign = deltaPct >= 0 ? 1 : -1;
586
- const nominal = Math.abs(deltaPct) === 1 ? 5 : 50;
587
- return this.getRideDisplay().adjustDevicePower(sign * nominal);
595
+ return this.getRideDisplay().adjustDevicePower(sign * this.getNominalErgWatts(deltaPct));
588
596
  }
589
597
  return deltaPct >= 0
590
598
  ? this.getWorkoutRide().powerUp(deltaPct)
@@ -764,6 +772,40 @@ let RidePageService = (() => {
764
772
  const wo = this.getWorkoutRide().getDashboardDisplayProperties();
765
773
  return { canStepBack: !!wo.canShowBackward, canStepForward: !!wo.canShowForward };
766
774
  }
775
+ getLoadControlProps() {
776
+ const mode = this.getLoadButtonMode();
777
+ if (mode === 'hidden')
778
+ return { visible: false };
779
+ if (mode === 'gear')
780
+ return { visible: true, label: 'Gear', buttons: { inc1: '+1', dec1: '-1', inc5: '+5', dec5: '-5' } };
781
+ if (this.isWorkoutAttached()) {
782
+ const buttons = this.getWorkoutRide().getDashboardDisplayProperties().loadButtons;
783
+ return { visible: true, label: 'Load', buttons };
784
+ }
785
+ const small = this.getNominalErgWatts(1);
786
+ const big = this.getNominalErgWatts(5);
787
+ return {
788
+ visible: true,
789
+ label: 'Load',
790
+ buttons: { inc1: `+${small}W`, dec1: `-${small}W`, inc5: `+${big}W`, dec5: `-${big}W` }
791
+ };
792
+ }
793
+ getNominalErgWatts(magnitude) {
794
+ return Math.abs(magnitude) === 1 ? 5 : 50;
795
+ }
796
+ onDeviceModeChanged() {
797
+ setTimeout(() => {
798
+ try {
799
+ if (!this.menuProps)
800
+ return;
801
+ this.menuProps = { ...this.menuProps, loadControl: this.getLoadControlProps() };
802
+ this.updatePageDisplay();
803
+ }
804
+ catch (err) {
805
+ this.logError(err, 'onDeviceModeChanged');
806
+ }
807
+ }, 0);
808
+ }
767
809
  getLastLogTime() {
768
810
  const logs = this.getActivityRide().getActivity()?.logs;
769
811
  if (!logs || logs.length === 0)
@@ -820,14 +862,18 @@ let RidePageService = (() => {
820
862
  }
821
863
  }
822
864
  buildPausedMenuProps() {
865
+ const loadControl = this.getLoadControlProps();
866
+ const showRideSettings = !this.isRideType('Workout');
823
867
  return this.isWorkoutAttached()
824
- ? { showResume: true, ...this.getStepFlags() }
825
- : { showResume: true };
868
+ ? { showResume: true, ...this.getStepFlags(), loadControl, showRideSettings }
869
+ : { showResume: true, loadControl, showRideSettings };
826
870
  }
827
871
  buildFinishedMenuProps() {
872
+ const loadControl = this.getLoadControlProps();
873
+ const showRideSettings = !this.isRideType('Workout');
828
874
  return this.isWorkoutAttached()
829
- ? { showResume: false, finished: true, canStepBack: false, canStepForward: false }
830
- : { showResume: false, finished: true };
875
+ ? { showResume: false, finished: true, canStepBack: false, canStepForward: false, loadControl, showRideSettings }
876
+ : { showResume: false, finished: true, loadControl, showRideSettings };
831
877
  }
832
878
  buildBaseDisplayProps() {
833
879
  const state = this.getRideDisplay().getState();
@@ -961,6 +1007,9 @@ let RidePageService = (() => {
961
1007
  getOnlineStatusMonitoring() {
962
1008
  return (0, monitoring_1.useOnlineStatusMonitoring)();
963
1009
  }
1010
+ getDeviceConfiguration() {
1011
+ return (0, devices_1.useDeviceConfiguration)();
1012
+ }
964
1013
  };
965
1014
  return RidePageService = _classThis;
966
1015
  })();
@@ -609,6 +609,8 @@ let RouteListService = (() => {
609
609
  }
610
610
  getRouteDescription(id) {
611
611
  try {
612
+ if (!id)
613
+ return undefined;
612
614
  return this.getVisibleRoutes().find(r => r.description.id === id)?.description;
613
615
  }
614
616
  catch (err) {
@@ -617,6 +619,8 @@ let RouteListService = (() => {
617
619
  }
618
620
  getRoute(id) {
619
621
  try {
622
+ if (!id)
623
+ return undefined;
620
624
  return this.getVisibleRoutes().find(r => r.description.id === id);
621
625
  }
622
626
  catch (err) {
@@ -44,6 +44,7 @@ import { Injectable } from "../../../base/decorators/Injection";
44
44
  import { useUnitConverter } from "../../../i18n";
45
45
  export const DB_VERSION = '5';
46
46
  export const DB_NAME = 'db';
47
+ const SHORT_RIDE_FILTER_CUTOFF = new Date('2026-08-28').getTime();
47
48
  let ActivitiesRepository = (() => {
48
49
  let _classDecorators = [Singleton];
49
50
  let _classDescriptor;
@@ -106,7 +107,7 @@ let ActivitiesRepository = (() => {
106
107
  this.write();
107
108
  }
108
109
  if (writeDetails) {
109
- this.writeDetails(activity);
110
+ await this.writeDetails(activity);
110
111
  }
111
112
  }
112
113
  migrate(activity, writeSummary = true) {
@@ -221,6 +222,16 @@ let ActivitiesRepository = (() => {
221
222
  }
222
223
  search(criteria) {
223
224
  let result = this.activities;
225
+ if (!this.isMobile()) {
226
+ result = result?.filter(ai => {
227
+ const { rideTime, startTime } = ai.summary;
228
+ if (rideTime < 1)
229
+ return false;
230
+ if (rideTime <= 30 && startTime < SHORT_RIDE_FILTER_CUTOFF)
231
+ return false;
232
+ return true;
233
+ });
234
+ }
224
235
  result = this.checkIdFilter(result, criteria);
225
236
  result = this.checkHashFilter(result, criteria);
226
237
  result = this.checkStartPosFilter(result, criteria);
@@ -472,7 +483,7 @@ let ActivitiesRepository = (() => {
472
483
  }
473
484
  async writeDetails(activity) {
474
485
  const name = activity.summary.name;
475
- this.getRepo().write(name, activity.details);
486
+ await this.getRepo().write(name, activity.details);
476
487
  }
477
488
  async scanForNewActivities() {
478
489
  try {
@@ -506,6 +517,13 @@ let ActivitiesRepository = (() => {
506
517
  getRouteList() {
507
518
  return useRouteList();
508
519
  }
520
+ isMobile() {
521
+ const { appInfo } = this.getBindings();
522
+ if (!appInfo) {
523
+ return false;
524
+ }
525
+ return appInfo?.getChannel() === 'mobile';
526
+ }
509
527
  getBindings() {
510
528
  return getBindings();
511
529
  }
@@ -251,7 +251,7 @@ let Activity = (() => {
251
251
  isRouteAvailable() {
252
252
  if (!this.details?.route)
253
253
  return false;
254
- if (this.details.routeType === 'Free-Ride')
254
+ if (this.details.routeType === 'Free-Ride' || this.details.routeType === 'None')
255
255
  return false;
256
256
  return this.getRouteList().getRouteDescription(this.details.route.id) !== undefined;
257
257
  }
@@ -274,7 +274,7 @@ let Activity = (() => {
274
274
  canStart() {
275
275
  if (!this.details?.route)
276
276
  return false;
277
- if (this.details.routeType === 'Free-Ride')
277
+ if (this.details.routeType === 'Free-Ride' || this.details.routeType === 'None')
278
278
  return false;
279
279
  if (this.details.routeType === 'Video') {
280
280
  const isOnline = this.getOnlineMonitoring().onlineStatus;
@@ -192,7 +192,7 @@ let ActivityRideService = (() => {
192
192
  this.disableDeviceHealthCheck();
193
193
  this.state = 'completed';
194
194
  this.updateActivityTime();
195
- this._save();
195
+ await this._save();
196
196
  this.emit('completed');
197
197
  this.tsPauseStart = undefined;
198
198
  delete this.tsStart;
@@ -530,7 +530,7 @@ let ActivityRideService = (() => {
530
530
  if (this.state !== 'completed') {
531
531
  await this.stop();
532
532
  }
533
- this.getRepo().delete(this.activity.id);
533
+ await this.getRepo().delete(this.activity.id);
534
534
  this.state = 'idle';
535
535
  }
536
536
  save() {
@@ -546,7 +546,7 @@ let ActivityRideService = (() => {
546
546
  let success = false;
547
547
  try {
548
548
  emit('start', success);
549
- await this._save();
549
+ this._save();
550
550
  success = await this._convertAndUpload();
551
551
  sleep(0).then(() => {
552
552
  delete this.saveObserver;
@@ -959,7 +959,7 @@ let ActivityRideService = (() => {
959
959
  await fs.writeFile(fileName, Buffer.from(data));
960
960
  this.activity.tcxFileName = fileName;
961
961
  }
962
- await this._save();
962
+ this._save();
963
963
  emit('save.done', format, true);
964
964
  return true;
965
965
  }
@@ -18,8 +18,11 @@ export function isVirtualShiftingEnabled(mode) {
18
18
  export function getLoadButtonMode(mode) {
19
19
  if (!mode)
20
20
  return 'power';
21
- if (mode.isSIM() || mode.isResistance()) {
22
- return isVirtualShiftingEnabled(mode) ? 'gear' : 'hidden';
23
- }
24
- return 'power';
21
+ if (mode.isERG())
22
+ return 'power';
23
+ if (mode.isSIM() && isVirtualShiftingEnabled(mode))
24
+ return 'gear';
25
+ if (mode.isResistance())
26
+ return 'gear';
27
+ return 'hidden';
25
28
  }
@@ -36,6 +36,7 @@ import { EventLogger } from "gd-eventlog";
36
36
  import { Injectable, Singleton } from "../../base/decorators";
37
37
  import { IncyclistPageService } from "../../base/pages";
38
38
  import { useRideDisplay } from "../display";
39
+ import { useDeviceConfiguration } from "../../devices";
39
40
  import { sleep } from "../../utils/sleep";
40
41
  import { useOnlineStatusMonitoring } from "../../monitoring";
41
42
  import { useActivityRide } from "../../activities";
@@ -61,6 +62,7 @@ let RidePageService = (() => {
61
62
  let _getActivityRide_decorators;
62
63
  let _getUserSettings_decorators;
63
64
  let _getOnlineStatusMonitoring_decorators;
65
+ let _getDeviceConfiguration_decorators;
64
66
  var RidePageService = class extends _classSuper {
65
67
  static { _classThis = this; }
66
68
  static {
@@ -70,11 +72,13 @@ let RidePageService = (() => {
70
72
  _getActivityRide_decorators = [Injectable];
71
73
  _getUserSettings_decorators = [Injectable];
72
74
  _getOnlineStatusMonitoring_decorators = [Injectable];
75
+ _getDeviceConfiguration_decorators = [Injectable];
73
76
  __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);
74
77
  __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);
75
78
  __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);
76
79
  __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);
77
80
  __esDecorate(this, null, _getOnlineStatusMonitoring_decorators, { kind: "method", name: "getOnlineStatusMonitoring", static: false, private: false, access: { has: obj => "getOnlineStatusMonitoring" in obj, get: obj => obj.getOnlineStatusMonitoring }, metadata: _metadata }, null, _instanceExtraInitializers);
81
+ __esDecorate(this, null, _getDeviceConfiguration_decorators, { kind: "method", name: "getDeviceConfiguration", static: false, private: false, access: { has: obj => "getDeviceConfiguration" in obj, get: obj => obj.getDeviceConfiguration }, metadata: _metadata }, null, _instanceExtraInitializers);
78
82
  __esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
79
83
  RidePageService = _classThis = _classDescriptor.value;
80
84
  if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
@@ -89,6 +93,7 @@ let RidePageService = (() => {
89
93
  menuProps = null;
90
94
  isInitialized = false;
91
95
  startGateProps = null;
96
+ onDeviceModeChangedBound = this.onDeviceModeChanged.bind(this);
92
97
  prevRidesVisibleRows = DEFAULT_PREV_RIDES_VISIBLE_ROWS;
93
98
  prevRidesMode = 'list';
94
99
  gestureHintDismissed = false;
@@ -140,6 +145,7 @@ let RidePageService = (() => {
140
145
  const registerAndStart = () => {
141
146
  this.registerHandlers(this.rideObserver, this.eventHandler);
142
147
  this.subscribeToWorkoutObserver();
148
+ this.getDeviceConfiguration().on('mode-changed', this.onDeviceModeChangedBound);
143
149
  const state = service.getState();
144
150
  if (state === 'Started' || state === 'Active' || state === 'Paused') {
145
151
  this.logError(new Error(`start() requested while ride is ${state}`), 'openPage');
@@ -184,6 +190,7 @@ let RidePageService = (() => {
184
190
  this.getRideDisplay().stop();
185
191
  this.unregisterHandlers(this.rideObserver, this.eventHandler);
186
192
  this.unsubscribeFromWorkoutObserver();
193
+ this.getDeviceConfiguration().off('mode-changed', this.onDeviceModeChangedBound);
187
194
  this.menuProps = null;
188
195
  this.isInitialized = false;
189
196
  super.closePage();
@@ -275,9 +282,11 @@ let RidePageService = (() => {
275
282
  onMenuOpen() {
276
283
  try {
277
284
  const state = this.getRideDisplay().getState();
285
+ const loadControl = this.getLoadControlProps();
286
+ const showRideSettings = !this.isRideType('Workout');
278
287
  this.menuProps = this.isWorkoutAttached()
279
- ? { showResume: state === 'Paused', ...this.getStepFlags() }
280
- : { showResume: state === 'Paused' };
288
+ ? { showResume: state === 'Paused', ...this.getStepFlags(), loadControl, showRideSettings }
289
+ : { showResume: state === 'Paused', loadControl, showRideSettings };
281
290
  this.updatePageDisplay();
282
291
  }
283
292
  catch (err) {
@@ -394,7 +403,7 @@ let RidePageService = (() => {
394
403
  const available = this.getCornerWidgetStates();
395
404
  if (available.length <= 1)
396
405
  return undefined;
397
- const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
406
+ const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'workout');
398
407
  return available.includes(current) ? current : available[0];
399
408
  }
400
409
  catch (err) {
@@ -411,7 +420,7 @@ let RidePageService = (() => {
411
420
  onToggleCornerWidget() {
412
421
  try {
413
422
  const available = this.getCornerWidgetStates();
414
- const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'elevation');
423
+ const current = this.getUserSettings().get(CORNER_WIDGET_SETTING_KEY, 'workout');
415
424
  const next = available[(available.indexOf(current) + 1) % available.length];
416
425
  this.getUserSettings().set(CORNER_WIDGET_SETTING_KEY, next);
417
426
  this.updatePageDisplay();
@@ -580,8 +589,7 @@ let RidePageService = (() => {
580
589
  const plainErgAdjustment = !this.getWorkoutRide().inUse() && this.getLoadButtonMode() === 'power';
581
590
  if (plainErgAdjustment) {
582
591
  const sign = deltaPct >= 0 ? 1 : -1;
583
- const nominal = Math.abs(deltaPct) === 1 ? 5 : 50;
584
- return this.getRideDisplay().adjustDevicePower(sign * nominal);
592
+ return this.getRideDisplay().adjustDevicePower(sign * this.getNominalErgWatts(deltaPct));
585
593
  }
586
594
  return deltaPct >= 0
587
595
  ? this.getWorkoutRide().powerUp(deltaPct)
@@ -761,6 +769,40 @@ let RidePageService = (() => {
761
769
  const wo = this.getWorkoutRide().getDashboardDisplayProperties();
762
770
  return { canStepBack: !!wo.canShowBackward, canStepForward: !!wo.canShowForward };
763
771
  }
772
+ getLoadControlProps() {
773
+ const mode = this.getLoadButtonMode();
774
+ if (mode === 'hidden')
775
+ return { visible: false };
776
+ if (mode === 'gear')
777
+ return { visible: true, label: 'Gear', buttons: { inc1: '+1', dec1: '-1', inc5: '+5', dec5: '-5' } };
778
+ if (this.isWorkoutAttached()) {
779
+ const buttons = this.getWorkoutRide().getDashboardDisplayProperties().loadButtons;
780
+ return { visible: true, label: 'Load', buttons };
781
+ }
782
+ const small = this.getNominalErgWatts(1);
783
+ const big = this.getNominalErgWatts(5);
784
+ return {
785
+ visible: true,
786
+ label: 'Load',
787
+ buttons: { inc1: `+${small}W`, dec1: `-${small}W`, inc5: `+${big}W`, dec5: `-${big}W` }
788
+ };
789
+ }
790
+ getNominalErgWatts(magnitude) {
791
+ return Math.abs(magnitude) === 1 ? 5 : 50;
792
+ }
793
+ onDeviceModeChanged() {
794
+ setTimeout(() => {
795
+ try {
796
+ if (!this.menuProps)
797
+ return;
798
+ this.menuProps = { ...this.menuProps, loadControl: this.getLoadControlProps() };
799
+ this.updatePageDisplay();
800
+ }
801
+ catch (err) {
802
+ this.logError(err, 'onDeviceModeChanged');
803
+ }
804
+ }, 0);
805
+ }
764
806
  getLastLogTime() {
765
807
  const logs = this.getActivityRide().getActivity()?.logs;
766
808
  if (!logs || logs.length === 0)
@@ -817,14 +859,18 @@ let RidePageService = (() => {
817
859
  }
818
860
  }
819
861
  buildPausedMenuProps() {
862
+ const loadControl = this.getLoadControlProps();
863
+ const showRideSettings = !this.isRideType('Workout');
820
864
  return this.isWorkoutAttached()
821
- ? { showResume: true, ...this.getStepFlags() }
822
- : { showResume: true };
865
+ ? { showResume: true, ...this.getStepFlags(), loadControl, showRideSettings }
866
+ : { showResume: true, loadControl, showRideSettings };
823
867
  }
824
868
  buildFinishedMenuProps() {
869
+ const loadControl = this.getLoadControlProps();
870
+ const showRideSettings = !this.isRideType('Workout');
825
871
  return this.isWorkoutAttached()
826
- ? { showResume: false, finished: true, canStepBack: false, canStepForward: false }
827
- : { showResume: false, finished: true };
872
+ ? { showResume: false, finished: true, canStepBack: false, canStepForward: false, loadControl, showRideSettings }
873
+ : { showResume: false, finished: true, loadControl, showRideSettings };
828
874
  }
829
875
  buildBaseDisplayProps() {
830
876
  const state = this.getRideDisplay().getState();
@@ -958,6 +1004,9 @@ let RidePageService = (() => {
958
1004
  getOnlineStatusMonitoring() {
959
1005
  return useOnlineStatusMonitoring();
960
1006
  }
1007
+ getDeviceConfiguration() {
1008
+ return useDeviceConfiguration();
1009
+ }
961
1010
  };
962
1011
  return RidePageService = _classThis;
963
1012
  })();
@@ -603,6 +603,8 @@ let RouteListService = (() => {
603
603
  }
604
604
  getRouteDescription(id) {
605
605
  try {
606
+ if (!id)
607
+ return undefined;
606
608
  return this.getVisibleRoutes().find(r => r.description.id === id)?.description;
607
609
  }
608
610
  catch (err) {
@@ -611,6 +613,8 @@ let RouteListService = (() => {
611
613
  }
612
614
  getRoute(id) {
613
615
  try {
616
+ if (!id)
617
+ return undefined;
614
618
  return this.getVisibleRoutes().find(r => r.description.id === id);
615
619
  }
616
620
  catch (err) {
@@ -55,6 +55,7 @@ export declare class ActivitiesRepository {
55
55
  protected logError(err: Error, fn: string, logProps?: any): void;
56
56
  protected getRepo(): JsonRepository;
57
57
  protected getRouteList(): import("../../../routes").RouteListService;
58
+ protected isMobile(): boolean;
58
59
  protected getBindings(): import("../../../api").IncyclistBindings;
59
60
  protected getUnitConverter(): import("../../../i18n").UnitConverterService;
60
61
  }
@@ -1,6 +1,6 @@
1
1
  import { IncyclistPageService } from "../../base/pages";
2
2
  import { CurrentRideDisplayProps, CurrentRideState, IObserver, RideType } from "../../types";
3
- import { AnyRidePageDisplayProps, GPXRidePageDisplayProps, IRidePageService, PrevRidesRowProps, RideMenuProps, RidePageDisplayProps, StartGateProps, VideoRidePageDisplayProps, WorkoutDashboardLine, WorkoutGestureHint, WorkoutGraphActuals, WorkoutGraphPlan, WorkoutRideMenuProps, WorkoutRidePageDisplayProps, WorkoutUpcomingSteps } from "./types";
3
+ import { AnyRidePageDisplayProps, GPXRidePageDisplayProps, IRidePageService, PrevRidesRowProps, LoadControlButtonLabels, RideMenuProps, RidePageDisplayProps, StartGateProps, VideoRidePageDisplayProps, WorkoutDashboardLine, WorkoutGestureHint, WorkoutGraphActuals, WorkoutGraphPlan, WorkoutRideMenuProps, WorkoutRidePageDisplayProps, WorkoutUpcomingSteps } from "./types";
4
4
  import { ISecretBinding } from "../../api/secret";
5
5
  import { PrevRidesListDisplayProps } from "../../activities";
6
6
  import type { LoadButtonMode, PowerAdjustmentResult, StepCountdownTick, WorkoutDisplayProperties } from "../../workouts/ride/types";
@@ -16,6 +16,7 @@ export declare class RidePageService extends IncyclistPageService implements IRi
16
16
  protected menuProps: RideMenuProps | null;
17
17
  protected isInitialized: boolean;
18
18
  protected startGateProps: StartGateProps | null;
19
+ protected onDeviceModeChangedBound: any;
19
20
  protected prevRidesVisibleRows: number;
20
21
  protected prevRidesMode: 'condensed' | 'list';
21
22
  protected gestureHintDismissed: boolean;
@@ -91,6 +92,13 @@ export declare class RidePageService extends IncyclistPageService implements IRi
91
92
  canStepBack: boolean;
92
93
  canStepForward: boolean;
93
94
  };
95
+ protected getLoadControlProps(): {
96
+ visible: boolean;
97
+ label?: 'Load' | 'Gear';
98
+ buttons?: LoadControlButtonLabels;
99
+ };
100
+ protected getNominalErgWatts(magnitude: number): number;
101
+ protected onDeviceModeChanged(): void;
94
102
  protected getLastLogTime(): number;
95
103
  protected getElapsedActivityTime(): number;
96
104
  protected getEmptyWorkoutDisplayProps(): WorkoutRidePageDisplayProps;
@@ -131,5 +139,6 @@ export declare class RidePageService extends IncyclistPageService implements IRi
131
139
  protected getActivityRide(): import("../../activities").ActivityRideService;
132
140
  protected getUserSettings(): import("../../settings").UserSettingsService;
133
141
  protected getOnlineStatusMonitoring(): import("../../monitoring").OnlineStateMonitoringService;
142
+ protected getDeviceConfiguration(): import("../../devices").DeviceConfigurationService;
134
143
  }
135
144
  export declare const getRidePageService: () => IRidePageService;
@@ -9,11 +9,23 @@ export interface StartGateProps {
9
9
  title: string;
10
10
  body: string;
11
11
  }
12
+ export interface LoadControlButtonLabels {
13
+ inc1: string;
14
+ dec1: string;
15
+ inc5: string;
16
+ dec5: string;
17
+ }
12
18
  export interface RideMenuProps {
13
19
  showResume?: boolean;
14
20
  finished?: boolean;
15
21
  canStepBack?: boolean;
16
22
  canStepForward?: boolean;
23
+ loadControl?: {
24
+ visible: boolean;
25
+ label?: 'Load' | 'Gear';
26
+ buttons?: LoadControlButtonLabels;
27
+ };
28
+ showRideSettings?: boolean;
17
29
  }
18
30
  export interface RidePageDisplayProps {
19
31
  rideState: CurrentRideState;
@@ -139,6 +151,12 @@ export interface WorkoutDashboardLine {
139
151
  export type WorkoutRideMenuProps = RideMenuProps & {
140
152
  canStepBack: boolean;
141
153
  canStepForward: boolean;
154
+ loadControl: {
155
+ visible: boolean;
156
+ label?: 'Load' | 'Gear';
157
+ buttons?: LoadControlButtonLabels;
158
+ };
159
+ showRideSettings: boolean;
142
160
  };
143
161
  export interface WorkoutGestureHint {
144
162
  visible: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "incyclist-services",
3
- "version": "1.7.119",
3
+ "version": "1.7.120",
4
4
  "peerDependencies": {
5
5
  "gd-eventlog": "^0.1.27"
6
6
  },