incyclist-services 1.7.76 → 1.7.78
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/cjs/activities/list/service.js +1 -1
- package/lib/cjs/activities/ride/service.js +2 -1
- package/lib/cjs/workouts/base/graph/index.js +18 -0
- package/lib/cjs/workouts/base/graph/series.js +205 -0
- package/lib/cjs/workouts/base/graph/types.js +2 -0
- package/lib/cjs/workouts/base/model/index.js +0 -1
- package/lib/cjs/workouts/calendar/service.js +14 -0
- package/lib/cjs/workouts/index.js +2 -0
- package/lib/cjs/workouts/list/cards/index.js +0 -1
- package/lib/cjs/workouts/list/index.js +0 -1
- package/lib/cjs/workouts/list/pageService.js +362 -5
- package/lib/cjs/workouts/list/service.js +39 -12
- package/lib/cjs/workouts/page/index.js +17 -0
- package/lib/cjs/workouts/page/service.js +455 -0
- package/lib/cjs/workouts/page/types.js +2 -0
- package/lib/cjs/workouts/ride/index.js +1 -0
- package/lib/cjs/workouts/ride/page/index.js +18 -0
- package/lib/cjs/workouts/ride/page/service.js +498 -0
- package/lib/cjs/workouts/ride/page/types.js +2 -0
- package/lib/cjs/workouts/ride/service.js +1 -1
- package/lib/cjs/workouts/types.js +2 -0
- package/lib/esm/activities/list/service.js +1 -1
- package/lib/esm/activities/ride/service.js +2 -1
- package/lib/esm/workouts/base/graph/index.js +2 -0
- package/lib/esm/workouts/base/graph/series.js +197 -0
- package/lib/esm/workouts/base/graph/types.js +1 -0
- package/lib/esm/workouts/base/model/index.js +0 -1
- package/lib/esm/workouts/calendar/service.js +14 -0
- package/lib/esm/workouts/index.js +2 -0
- package/lib/esm/workouts/list/cards/index.js +0 -1
- package/lib/esm/workouts/list/index.js +0 -1
- package/lib/esm/workouts/list/pageService.js +362 -5
- package/lib/esm/workouts/list/service.js +39 -12
- package/lib/esm/workouts/page/index.js +1 -0
- package/lib/esm/workouts/page/service.js +451 -0
- package/lib/esm/workouts/page/types.js +1 -0
- package/lib/esm/workouts/ride/index.js +1 -0
- package/lib/esm/workouts/ride/page/index.js +2 -0
- package/lib/esm/workouts/ride/page/service.js +494 -0
- package/lib/esm/workouts/ride/page/types.js +1 -0
- package/lib/esm/workouts/ride/service.js +1 -1
- package/lib/esm/workouts/types.js +1 -0
- package/lib/types/types.d.ts +1 -0
- package/lib/types/workouts/base/graph/index.d.ts +2 -0
- package/lib/types/workouts/base/graph/series.d.ts +18 -0
- package/lib/types/workouts/base/graph/types.d.ts +11 -0
- package/lib/types/workouts/base/model/index.d.ts +0 -1
- package/lib/types/workouts/base/parsers/intervals/parser.d.ts +2 -1
- package/lib/types/workouts/calendar/service.d.ts +1 -0
- package/lib/types/workouts/index.d.ts +2 -0
- package/lib/types/workouts/list/cards/index.d.ts +0 -1
- package/lib/types/workouts/list/index.d.ts +0 -1
- package/lib/types/workouts/list/pageService.d.ts +136 -4
- package/lib/types/workouts/list/service.d.ts +4 -0
- package/lib/types/workouts/list/types.d.ts +1 -1
- package/lib/types/workouts/page/index.d.ts +1 -0
- package/lib/types/workouts/page/service.d.ts +57 -0
- package/lib/types/workouts/page/types.d.ts +95 -0
- package/lib/types/workouts/ride/index.d.ts +1 -0
- package/lib/types/workouts/ride/page/index.d.ts +2 -0
- package/lib/types/workouts/ride/page/service.d.ts +70 -0
- package/lib/types/workouts/ride/page/types.d.ts +71 -0
- package/lib/types/workouts/ride/service.d.ts +2 -1
- package/lib/types/workouts/ride/types.d.ts +3 -0
- package/lib/types/workouts/types.d.ts +8 -0
- package/package.json +1 -1
|
@@ -32,6 +32,7 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
32
32
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
33
|
done = true;
|
|
34
34
|
};
|
|
35
|
+
import { getBindings } from "../../api";
|
|
35
36
|
import { CardList } from "../../base/cardlist";
|
|
36
37
|
import { IncyclistService } from "../../base/service";
|
|
37
38
|
import { ListObserver, Singleton } from "../../base/types";
|
|
@@ -57,14 +58,17 @@ let WorkoutListService = (() => {
|
|
|
57
58
|
let _instanceExtraInitializers = [];
|
|
58
59
|
let _getWorkoutCalendar_decorators;
|
|
59
60
|
let _getAppState_decorators;
|
|
61
|
+
let _getBindings_decorators;
|
|
60
62
|
var WorkoutListService = class extends _classSuper {
|
|
61
63
|
static { _classThis = this; }
|
|
62
64
|
static {
|
|
63
65
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
64
66
|
_getWorkoutCalendar_decorators = [Injectable];
|
|
65
67
|
_getAppState_decorators = [Injectable];
|
|
68
|
+
_getBindings_decorators = [Injectable];
|
|
66
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);
|
|
67
70
|
__esDecorate(this, null, _getAppState_decorators, { kind: "method", name: "getAppState", static: false, private: false, access: { has: obj => "getAppState" in obj, get: obj => obj.getAppState }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
71
|
+
__esDecorate(this, null, _getBindings_decorators, { kind: "method", name: "getBindings", static: false, private: false, access: { has: obj => "getBindings" in obj, get: obj => obj.getBindings }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
68
72
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
69
73
|
WorkoutListService = _classThis = _classDescriptor.value;
|
|
70
74
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -81,6 +85,7 @@ let WorkoutListService = (() => {
|
|
|
81
85
|
language;
|
|
82
86
|
selectedWorkout;
|
|
83
87
|
ftp;
|
|
88
|
+
useErgModeOverride;
|
|
84
89
|
scheduledToday;
|
|
85
90
|
scheduledList;
|
|
86
91
|
selectedCard;
|
|
@@ -167,7 +172,8 @@ let WorkoutListService = (() => {
|
|
|
167
172
|
let useErgMode = true;
|
|
168
173
|
try {
|
|
169
174
|
const userSettings = this.getUserSettings();
|
|
170
|
-
|
|
175
|
+
const globalErgMode = userSettings.get('preferences.useErgMode', true);
|
|
176
|
+
useErgMode = this.useErgModeOverride ?? globalErgMode;
|
|
171
177
|
const user = userSettings.get('user', undefined);
|
|
172
178
|
ftp = this.ftp ?? user?.ftp ?? 200;
|
|
173
179
|
}
|
|
@@ -178,8 +184,7 @@ let WorkoutListService = (() => {
|
|
|
178
184
|
}
|
|
179
185
|
setStartSettings(settings) {
|
|
180
186
|
try {
|
|
181
|
-
|
|
182
|
-
userSettings.set('preferences.useErgMode', settings?.useErgMode);
|
|
187
|
+
this.useErgModeOverride = settings?.useErgMode;
|
|
183
188
|
this.ftp = settings?.ftp;
|
|
184
189
|
}
|
|
185
190
|
catch (err) {
|
|
@@ -234,7 +239,9 @@ let WorkoutListService = (() => {
|
|
|
234
239
|
this.getWorkoutCalendar().once('scheduled', (event) => {
|
|
235
240
|
this.scheduledToday = event;
|
|
236
241
|
this.getAppState().setState('scheduledToday', event.workout.id);
|
|
237
|
-
this.
|
|
242
|
+
if (!this.isMobile()) {
|
|
243
|
+
this.getAppState().setPersistedState('page', 'workouts');
|
|
244
|
+
}
|
|
238
245
|
});
|
|
239
246
|
this.getWorkoutCalendar().init();
|
|
240
247
|
this.preloadObserver.start()
|
|
@@ -336,13 +343,15 @@ let WorkoutListService = (() => {
|
|
|
336
343
|
getScheduledWorkouts(scheduled) {
|
|
337
344
|
const schedList = new CardList('scheduled', 'Scheduled Workouts');
|
|
338
345
|
scheduled.forEach(w => schedList.add(new ScheduledWorkoutCard(w)));
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
c.
|
|
344
|
-
|
|
345
|
-
|
|
346
|
+
if (!this.isMobile()) {
|
|
347
|
+
const today = this.getAppState().getState('scheduledToday');
|
|
348
|
+
if (today) {
|
|
349
|
+
schedList.getCards().forEach(c => {
|
|
350
|
+
if (c.getId() === today) {
|
|
351
|
+
c.select();
|
|
352
|
+
}
|
|
353
|
+
});
|
|
354
|
+
}
|
|
346
355
|
}
|
|
347
356
|
const newList = (this.scheduledList === undefined || this.scheduledList === null);
|
|
348
357
|
if (newList) {
|
|
@@ -427,7 +436,7 @@ let WorkoutListService = (() => {
|
|
|
427
436
|
if (typeof target === 'string') {
|
|
428
437
|
targetList = this.lists.find(l => l.getTitle() === target);
|
|
429
438
|
if (!targetList)
|
|
430
|
-
|
|
439
|
+
targetList = this.addList(target);
|
|
431
440
|
}
|
|
432
441
|
else {
|
|
433
442
|
targetList = target;
|
|
@@ -441,6 +450,18 @@ let WorkoutListService = (() => {
|
|
|
441
450
|
this.logError(err, 'moveCard');
|
|
442
451
|
}
|
|
443
452
|
}
|
|
453
|
+
deleteWorkout(id) {
|
|
454
|
+
try {
|
|
455
|
+
const { card } = this.findCard(id) ?? {};
|
|
456
|
+
if (!card)
|
|
457
|
+
return PromiseObserver.alwaysReturning(false);
|
|
458
|
+
return card.delete();
|
|
459
|
+
}
|
|
460
|
+
catch (err) {
|
|
461
|
+
this.logError(err, 'deleteWorkout');
|
|
462
|
+
return PromiseObserver.alwaysReturning(false);
|
|
463
|
+
}
|
|
464
|
+
}
|
|
444
465
|
canDisplayStart() {
|
|
445
466
|
const routes = this.getRouteList();
|
|
446
467
|
return valid(routes.getSelected());
|
|
@@ -645,6 +666,12 @@ let WorkoutListService = (() => {
|
|
|
645
666
|
getAppState() {
|
|
646
667
|
return useAppState();
|
|
647
668
|
}
|
|
669
|
+
isMobile() {
|
|
670
|
+
return this.getBindings()?.appInfo?.getChannel() === 'mobile';
|
|
671
|
+
}
|
|
672
|
+
getBindings() {
|
|
673
|
+
return getBindings();
|
|
674
|
+
}
|
|
648
675
|
getRepo() {
|
|
649
676
|
if (!this.db)
|
|
650
677
|
this.db = new WorkoutsDbLoader();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export * from './service';
|
|
@@ -0,0 +1,451 @@
|
|
|
1
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
2
|
+
var useValue = arguments.length > 2;
|
|
3
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
4
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
5
|
+
}
|
|
6
|
+
return useValue ? value : void 0;
|
|
7
|
+
};
|
|
8
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
9
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
10
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
11
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
12
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
13
|
+
var _, done = false;
|
|
14
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
15
|
+
var context = {};
|
|
16
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
17
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
18
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
19
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
20
|
+
if (kind === "accessor") {
|
|
21
|
+
if (result === void 0) continue;
|
|
22
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
23
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
24
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
25
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
26
|
+
}
|
|
27
|
+
else if (_ = accept(result)) {
|
|
28
|
+
if (kind === "field") initializers.unshift(_);
|
|
29
|
+
else descriptor[key] = _;
|
|
30
|
+
}
|
|
31
|
+
}
|
|
32
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
33
|
+
done = true;
|
|
34
|
+
};
|
|
35
|
+
import { Singleton } from "../../base/types";
|
|
36
|
+
import { IncyclistPageService } from "../../base/pages";
|
|
37
|
+
import { Injectable } from "../../base/decorators";
|
|
38
|
+
import { useAppState } from "../../appstate";
|
|
39
|
+
import { Observer } from "../../base/types/observer";
|
|
40
|
+
import { useUserSettings } from "../../settings";
|
|
41
|
+
import { useWorkoutCalendar } from "../calendar";
|
|
42
|
+
import { useWorkoutList } from "../list/service";
|
|
43
|
+
const DEFAULT_IMPORT_GROUP = 'My Workouts';
|
|
44
|
+
const UPCOMING_COLLAPSED_COUNT = 3;
|
|
45
|
+
let WorkoutListPageService = (() => {
|
|
46
|
+
let _classDecorators = [Singleton];
|
|
47
|
+
let _classDescriptor;
|
|
48
|
+
let _classExtraInitializers = [];
|
|
49
|
+
let _classThis;
|
|
50
|
+
let _classSuper = IncyclistPageService;
|
|
51
|
+
let _instanceExtraInitializers = [];
|
|
52
|
+
let _getWorkoutList_decorators;
|
|
53
|
+
let _getWorkoutCalendar_decorators;
|
|
54
|
+
let _getUserSettings_decorators;
|
|
55
|
+
let _getAppState_decorators;
|
|
56
|
+
var WorkoutListPageService = class extends _classSuper {
|
|
57
|
+
static { _classThis = this; }
|
|
58
|
+
static {
|
|
59
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
60
|
+
_getWorkoutList_decorators = [Injectable];
|
|
61
|
+
_getWorkoutCalendar_decorators = [Injectable];
|
|
62
|
+
_getUserSettings_decorators = [Injectable];
|
|
63
|
+
_getAppState_decorators = [Injectable];
|
|
64
|
+
__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
|
+
__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
|
+
__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);
|
|
67
|
+
__esDecorate(this, null, _getAppState_decorators, { kind: "method", name: "getAppState", static: false, private: false, access: { has: obj => "getAppState" in obj, get: obj => obj.getAppState }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
68
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
69
|
+
WorkoutListPageService = _classThis = _classDescriptor.value;
|
|
70
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
71
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
72
|
+
}
|
|
73
|
+
groupFilter = (__runInitializers(this, _instanceExtraInitializers), null);
|
|
74
|
+
importPhase;
|
|
75
|
+
importGroup;
|
|
76
|
+
importingFileName;
|
|
77
|
+
importResult;
|
|
78
|
+
importError;
|
|
79
|
+
listObserver;
|
|
80
|
+
listUpdateHandler = this.emitPageUpdate.bind(this);
|
|
81
|
+
calendarUpdateHandler = this.emitPageUpdate.bind(this);
|
|
82
|
+
constructor() {
|
|
83
|
+
super('WorkoutListPage');
|
|
84
|
+
}
|
|
85
|
+
openPage() {
|
|
86
|
+
try {
|
|
87
|
+
super.openPage();
|
|
88
|
+
this.logEvent({ message: 'page shown', page: 'Workouts' });
|
|
89
|
+
const { observer } = this.getWorkoutList().open();
|
|
90
|
+
this.listObserver = observer;
|
|
91
|
+
this.listObserver?.on('started', this.listUpdateHandler);
|
|
92
|
+
this.listObserver?.on('loading', this.listUpdateHandler);
|
|
93
|
+
this.listObserver?.on('loaded', this.listUpdateHandler);
|
|
94
|
+
this.listObserver?.on('updated', this.listUpdateHandler);
|
|
95
|
+
this.getWorkoutCalendar().on('updated', this.calendarUpdateHandler);
|
|
96
|
+
this.emitPageUpdate();
|
|
97
|
+
}
|
|
98
|
+
catch (err) {
|
|
99
|
+
this.logError(err, 'openPage');
|
|
100
|
+
}
|
|
101
|
+
return this.getPageObserver();
|
|
102
|
+
}
|
|
103
|
+
closePage() {
|
|
104
|
+
try {
|
|
105
|
+
this.getWorkoutList().close();
|
|
106
|
+
this.listObserver?.off('started', this.listUpdateHandler);
|
|
107
|
+
this.listObserver?.off('loading', this.listUpdateHandler);
|
|
108
|
+
this.listObserver?.off('loaded', this.listUpdateHandler);
|
|
109
|
+
this.listObserver?.off('updated', this.listUpdateHandler);
|
|
110
|
+
this.getWorkoutCalendar().off('updated', this.calendarUpdateHandler);
|
|
111
|
+
delete this.listObserver;
|
|
112
|
+
this.logEvent({ message: 'page closed', page: 'Workouts' });
|
|
113
|
+
super.closePage();
|
|
114
|
+
}
|
|
115
|
+
catch (err) {
|
|
116
|
+
this.logError(err, 'closePage');
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
getPageDisplayProps() {
|
|
120
|
+
try {
|
|
121
|
+
if (!this.getAppState().hasFeature('MOBILE_WORKOUTS')) {
|
|
122
|
+
return { pageType: 'placeholder' };
|
|
123
|
+
}
|
|
124
|
+
const service = this.getWorkoutList();
|
|
125
|
+
const loading = service.isStillLoading();
|
|
126
|
+
const upcoming = this.getUpcomingTrainingProps();
|
|
127
|
+
const allWorkouts = this.getAllWorkoutItems();
|
|
128
|
+
const groups = this.getGroupFilterProps();
|
|
129
|
+
const workouts = groups.selected ? allWorkouts.filter(w => w.group === groups.selected) : allWorkouts;
|
|
130
|
+
const selectedId = service.getSelected()?.id ?? null;
|
|
131
|
+
const isEmpty = allWorkouts.length === 0;
|
|
132
|
+
return { pageType: 'list', loading, upcoming, groups, workouts, selectedId, isEmpty };
|
|
133
|
+
}
|
|
134
|
+
catch (err) {
|
|
135
|
+
this.logError(err, 'getPageDisplayProps');
|
|
136
|
+
return {};
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
getWorkoutDetailsProps(id) {
|
|
140
|
+
try {
|
|
141
|
+
const card = this.findWorkoutCard(id);
|
|
142
|
+
if (!card)
|
|
143
|
+
return null;
|
|
144
|
+
const workout = card.getData();
|
|
145
|
+
const settingsProps = card.openSettings();
|
|
146
|
+
const isScheduled = card.getCardType() === 'ScheduledWorkout';
|
|
147
|
+
return {
|
|
148
|
+
id,
|
|
149
|
+
title: card.getTitle(),
|
|
150
|
+
description: workout?.description,
|
|
151
|
+
duration: settingsProps.duration,
|
|
152
|
+
workout,
|
|
153
|
+
ftp: settingsProps.settings?.ftp,
|
|
154
|
+
ftpRequired: settingsProps.ftpRequired,
|
|
155
|
+
useErgMode: settingsProps.settings?.useErgMode,
|
|
156
|
+
canStart: settingsProps.canStart,
|
|
157
|
+
canStartWorkoutOnly: settingsProps.canStartWorkoutOnly,
|
|
158
|
+
groups: settingsProps.categories,
|
|
159
|
+
group: settingsProps.category,
|
|
160
|
+
canDelete: card.canDelete(),
|
|
161
|
+
isScheduled,
|
|
162
|
+
date: isScheduled ? settingsProps.date : undefined
|
|
163
|
+
};
|
|
164
|
+
}
|
|
165
|
+
catch (err) {
|
|
166
|
+
this.logError(err, 'getWorkoutDetailsProps');
|
|
167
|
+
return null;
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
getImportDisplayProps() {
|
|
171
|
+
try {
|
|
172
|
+
const phase = this.importPhase ?? 'landing';
|
|
173
|
+
const knownGroups = this.getKnownGroups();
|
|
174
|
+
const group = this.importGroup ?? this.getLastUsedImportGroup();
|
|
175
|
+
const props = { phase, group, knownGroups };
|
|
176
|
+
if (phase === 'importing')
|
|
177
|
+
props.importing = { fileName: this.importingFileName };
|
|
178
|
+
if (phase === 'result')
|
|
179
|
+
props.result = this.importResult;
|
|
180
|
+
if (phase === 'error')
|
|
181
|
+
props.error = this.importError;
|
|
182
|
+
return props;
|
|
183
|
+
}
|
|
184
|
+
catch (err) {
|
|
185
|
+
this.logError(err, 'getImportDisplayProps');
|
|
186
|
+
return { phase: 'landing', group: DEFAULT_IMPORT_GROUP, knownGroups: [] };
|
|
187
|
+
}
|
|
188
|
+
}
|
|
189
|
+
onSelectGroup(group) {
|
|
190
|
+
try {
|
|
191
|
+
this.groupFilter = group;
|
|
192
|
+
this.emitPageUpdate();
|
|
193
|
+
}
|
|
194
|
+
catch (err) {
|
|
195
|
+
this.logError(err, 'onSelectGroup');
|
|
196
|
+
}
|
|
197
|
+
}
|
|
198
|
+
onOpenDetails(id) {
|
|
199
|
+
this.logEvent({ message: 'details opened', id });
|
|
200
|
+
}
|
|
201
|
+
onCloseDetails() {
|
|
202
|
+
this.logEvent({ message: 'details closed' });
|
|
203
|
+
}
|
|
204
|
+
onSetFtp(ftp) {
|
|
205
|
+
try {
|
|
206
|
+
const current = this.getWorkoutList().getStartSettings();
|
|
207
|
+
this.getWorkoutList().setStartSettings({ ...current, ftp });
|
|
208
|
+
this.emitPageUpdate();
|
|
209
|
+
}
|
|
210
|
+
catch (err) {
|
|
211
|
+
this.logError(err, 'onSetFtp');
|
|
212
|
+
}
|
|
213
|
+
}
|
|
214
|
+
onSetErgMode(enabled) {
|
|
215
|
+
try {
|
|
216
|
+
const current = this.getWorkoutList().getStartSettings();
|
|
217
|
+
this.getWorkoutList().setStartSettings({ ...current, useErgMode: enabled });
|
|
218
|
+
this.emitPageUpdate();
|
|
219
|
+
}
|
|
220
|
+
catch (err) {
|
|
221
|
+
this.logError(err, 'onSetErgMode');
|
|
222
|
+
}
|
|
223
|
+
}
|
|
224
|
+
onChangeGroup(id, group) {
|
|
225
|
+
try {
|
|
226
|
+
const card = this.findWorkoutCard(id);
|
|
227
|
+
card?.move(group);
|
|
228
|
+
this.emitPageUpdate();
|
|
229
|
+
}
|
|
230
|
+
catch (err) {
|
|
231
|
+
this.logError(err, 'onChangeGroup');
|
|
232
|
+
}
|
|
233
|
+
}
|
|
234
|
+
async onDelete(id) {
|
|
235
|
+
try {
|
|
236
|
+
const observer = this.getWorkoutList().deleteWorkout(id);
|
|
237
|
+
const deleted = await observer.wait();
|
|
238
|
+
this.emitPageUpdate();
|
|
239
|
+
return !!deleted;
|
|
240
|
+
}
|
|
241
|
+
catch (err) {
|
|
242
|
+
this.logError(err, 'onDelete');
|
|
243
|
+
return false;
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
onStart(id, opts) {
|
|
247
|
+
try {
|
|
248
|
+
const card = this.findWorkoutCard(id);
|
|
249
|
+
if (!card)
|
|
250
|
+
return;
|
|
251
|
+
const settings = this.getWorkoutList().getStartSettings();
|
|
252
|
+
card.select({ ...settings, noRoute: opts?.noRoute });
|
|
253
|
+
this.getPageObserver()?.emit('start-ride', { id, noRoute: opts?.noRoute });
|
|
254
|
+
}
|
|
255
|
+
catch (err) {
|
|
256
|
+
this.logError(err, 'onStart');
|
|
257
|
+
}
|
|
258
|
+
}
|
|
259
|
+
onMarkForRoute(id) {
|
|
260
|
+
try {
|
|
261
|
+
const card = this.findWorkoutCard(id);
|
|
262
|
+
if (!card)
|
|
263
|
+
return;
|
|
264
|
+
const settings = this.getWorkoutList().getStartSettings();
|
|
265
|
+
card.select({ ...settings, noRoute: false });
|
|
266
|
+
this.emitPageUpdate();
|
|
267
|
+
}
|
|
268
|
+
catch (err) {
|
|
269
|
+
this.logError(err, 'onMarkForRoute');
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
onClearSelection() {
|
|
273
|
+
try {
|
|
274
|
+
this.getWorkoutList().unselect();
|
|
275
|
+
this.emitPageUpdate();
|
|
276
|
+
}
|
|
277
|
+
catch (err) {
|
|
278
|
+
this.logError(err, 'onClearSelection');
|
|
279
|
+
}
|
|
280
|
+
}
|
|
281
|
+
onImportOpen() {
|
|
282
|
+
try {
|
|
283
|
+
this.importPhase = 'landing';
|
|
284
|
+
this.importGroup = this.getLastUsedImportGroup();
|
|
285
|
+
delete this.importError;
|
|
286
|
+
delete this.importResult;
|
|
287
|
+
this.emitImportUpdate();
|
|
288
|
+
}
|
|
289
|
+
catch (err) {
|
|
290
|
+
this.logError(err, 'onImportOpen');
|
|
291
|
+
}
|
|
292
|
+
}
|
|
293
|
+
onImportGroupChange(name) {
|
|
294
|
+
try {
|
|
295
|
+
this.importGroup = name;
|
|
296
|
+
this.emitImportUpdate();
|
|
297
|
+
}
|
|
298
|
+
catch (err) {
|
|
299
|
+
this.logError(err, 'onImportGroupChange');
|
|
300
|
+
}
|
|
301
|
+
}
|
|
302
|
+
onImportFile(file) {
|
|
303
|
+
const observer = new Observer();
|
|
304
|
+
try {
|
|
305
|
+
const group = this.importGroup;
|
|
306
|
+
this.importPhase = 'importing';
|
|
307
|
+
this.importingFileName = file?.name;
|
|
308
|
+
this.emitImportUpdate();
|
|
309
|
+
this.getWorkoutList().import(file, { showImportCards: false })
|
|
310
|
+
.then(([card]) => {
|
|
311
|
+
if (group && group !== DEFAULT_IMPORT_GROUP)
|
|
312
|
+
card.move(group);
|
|
313
|
+
this.persistLastUsedImportGroup(group);
|
|
314
|
+
this.importPhase = 'result';
|
|
315
|
+
this.importResult = { workoutName: card.getTitle(), group };
|
|
316
|
+
observer.emit('success');
|
|
317
|
+
this.emitImportUpdate();
|
|
318
|
+
})
|
|
319
|
+
.catch((err) => {
|
|
320
|
+
this.importPhase = 'error';
|
|
321
|
+
this.importError = err?.message;
|
|
322
|
+
observer.emit('error', err);
|
|
323
|
+
this.emitImportUpdate();
|
|
324
|
+
});
|
|
325
|
+
}
|
|
326
|
+
catch (err) {
|
|
327
|
+
this.logError(err, 'onImportFile');
|
|
328
|
+
}
|
|
329
|
+
return observer;
|
|
330
|
+
}
|
|
331
|
+
onImportClose() {
|
|
332
|
+
try {
|
|
333
|
+
delete this.importPhase;
|
|
334
|
+
delete this.importingFileName;
|
|
335
|
+
delete this.importResult;
|
|
336
|
+
delete this.importError;
|
|
337
|
+
this.emitImportUpdate();
|
|
338
|
+
}
|
|
339
|
+
catch (err) {
|
|
340
|
+
this.logError(err, 'onImportClose');
|
|
341
|
+
}
|
|
342
|
+
}
|
|
343
|
+
getUpcomingTrainingProps() {
|
|
344
|
+
const calendar = this.getWorkoutCalendar();
|
|
345
|
+
const scheduled = calendar.getScheduledWorkouts();
|
|
346
|
+
if (!scheduled || scheduled.length === 0)
|
|
347
|
+
return null;
|
|
348
|
+
const todayId = calendar.getScheduledToday()?.id ?? null;
|
|
349
|
+
const selectedWorkout = this.getWorkoutList().getSelected();
|
|
350
|
+
const items = scheduled.map(w => ({
|
|
351
|
+
id: w.id,
|
|
352
|
+
title: w.workout?.name,
|
|
353
|
+
date: w.day,
|
|
354
|
+
duration: this.formatDuration(w.workout?.duration),
|
|
355
|
+
isToday: todayId !== null && w.id === todayId,
|
|
356
|
+
selected: selectedWorkout?.id !== undefined && selectedWorkout.id === w.workout?.id,
|
|
357
|
+
workout: w.workout
|
|
358
|
+
}));
|
|
359
|
+
return { items, collapsedCount: UPCOMING_COLLAPSED_COUNT, todayId };
|
|
360
|
+
}
|
|
361
|
+
getGroupFilterProps() {
|
|
362
|
+
const available = this.getKnownGroups();
|
|
363
|
+
return { available, selected: this.groupFilter };
|
|
364
|
+
}
|
|
365
|
+
getKnownGroups() {
|
|
366
|
+
const lists = this.getWorkoutList().getLists(false) ?? [];
|
|
367
|
+
return lists.filter(l => l.getId() !== 'scheduled').map(l => l.getTitle());
|
|
368
|
+
}
|
|
369
|
+
getAllWorkoutItems() {
|
|
370
|
+
const lists = this.getWorkoutList().getLists(false) ?? [];
|
|
371
|
+
const items = [];
|
|
372
|
+
lists.forEach(list => {
|
|
373
|
+
if (list.getId() === 'scheduled')
|
|
374
|
+
return;
|
|
375
|
+
list.getCards().forEach(card => {
|
|
376
|
+
if (card.getCardType() !== 'Workout')
|
|
377
|
+
return;
|
|
378
|
+
const workoutCard = card;
|
|
379
|
+
const props = workoutCard.getDisplayProperties();
|
|
380
|
+
items.push({
|
|
381
|
+
id: workoutCard.getId(),
|
|
382
|
+
title: props.title,
|
|
383
|
+
group: list.getTitle(),
|
|
384
|
+
duration: props.duration,
|
|
385
|
+
selected: props.selected,
|
|
386
|
+
canDelete: props.canDelete,
|
|
387
|
+
workout: props.workout
|
|
388
|
+
});
|
|
389
|
+
});
|
|
390
|
+
});
|
|
391
|
+
return items;
|
|
392
|
+
}
|
|
393
|
+
findWorkoutCard(id) {
|
|
394
|
+
const lists = this.getWorkoutList().getLists(false) ?? [];
|
|
395
|
+
for (const list of lists) {
|
|
396
|
+
const card = list.getCards().find(c => c.getId() === id);
|
|
397
|
+
if (card)
|
|
398
|
+
return card;
|
|
399
|
+
}
|
|
400
|
+
return undefined;
|
|
401
|
+
}
|
|
402
|
+
getLastUsedImportGroup() {
|
|
403
|
+
return this.getUserSettings().get('preferences.workouts.lastImportGroup', DEFAULT_IMPORT_GROUP);
|
|
404
|
+
}
|
|
405
|
+
persistLastUsedImportGroup(group) {
|
|
406
|
+
try {
|
|
407
|
+
this.getUserSettings().set('preferences.workouts.lastImportGroup', group);
|
|
408
|
+
}
|
|
409
|
+
catch (err) {
|
|
410
|
+
this.logError(err, 'persistLastUsedImportGroup');
|
|
411
|
+
}
|
|
412
|
+
}
|
|
413
|
+
formatDuration(duration) {
|
|
414
|
+
if (duration === undefined || duration === null)
|
|
415
|
+
return '';
|
|
416
|
+
if (duration < 120)
|
|
417
|
+
return `${duration.toFixed(0)}s`;
|
|
418
|
+
if (duration % 60 === 0)
|
|
419
|
+
return `${duration / 60}min`;
|
|
420
|
+
const secVal = duration % 60;
|
|
421
|
+
const minVal = (duration - secVal) / 60 % 60;
|
|
422
|
+
const h = Math.floor((duration - secVal - minVal * 60) / 3600);
|
|
423
|
+
const sec = secVal < 10 ? `0${secVal}` : secVal;
|
|
424
|
+
const min = minVal < 10 ? `0${minVal}` : minVal;
|
|
425
|
+
if (h > 0)
|
|
426
|
+
return `${h}:${min}:${sec}`;
|
|
427
|
+
return `${min}:${sec}`;
|
|
428
|
+
}
|
|
429
|
+
emitPageUpdate() {
|
|
430
|
+
this.getPageObserver()?.emit('page-update');
|
|
431
|
+
}
|
|
432
|
+
emitImportUpdate() {
|
|
433
|
+
this.getPageObserver()?.emit('import-update');
|
|
434
|
+
}
|
|
435
|
+
getWorkoutList() {
|
|
436
|
+
return useWorkoutList();
|
|
437
|
+
}
|
|
438
|
+
getWorkoutCalendar() {
|
|
439
|
+
return useWorkoutCalendar();
|
|
440
|
+
}
|
|
441
|
+
getUserSettings() {
|
|
442
|
+
return useUserSettings();
|
|
443
|
+
}
|
|
444
|
+
getAppState() {
|
|
445
|
+
return useAppState();
|
|
446
|
+
}
|
|
447
|
+
};
|
|
448
|
+
return WorkoutListPageService = _classThis;
|
|
449
|
+
})();
|
|
450
|
+
export { WorkoutListPageService };
|
|
451
|
+
export const getWorkoutListPageService = () => new WorkoutListPageService();
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|