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.
- package/lib/cjs/activities/base/repo/db.js +20 -2
- package/lib/cjs/activities/base/utils/activity.js +2 -2
- package/lib/cjs/activities/ride/service.js +4 -4
- package/lib/cjs/devices/ride/cyclingMode.js +7 -4
- package/lib/cjs/ride/page/service.js +59 -10
- package/lib/cjs/routes/list/service.js +4 -0
- package/lib/esm/activities/base/repo/db.js +20 -2
- package/lib/esm/activities/base/utils/activity.js +2 -2
- package/lib/esm/activities/ride/service.js +4 -4
- package/lib/esm/devices/ride/cyclingMode.js +7 -4
- package/lib/esm/ride/page/service.js +59 -10
- package/lib/esm/routes/list/service.js +4 -0
- package/lib/types/activities/base/repo/db.d.ts +1 -0
- package/lib/types/ride/page/service.d.ts +10 -1
- package/lib/types/ride/page/types.d.ts +18 -0
- package/package.json +1 -1
|
@@ -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
|
-
|
|
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
|
-
|
|
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.
|
|
26
|
-
return
|
|
27
|
-
|
|
28
|
-
|
|
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, '
|
|
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, '
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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.
|
|
22
|
-
return
|
|
23
|
-
|
|
24
|
-
|
|
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, '
|
|
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, '
|
|
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
|
-
|
|
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;
|