incyclist-services 1.7.108 → 1.7.110
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/utils.js +16 -14
- package/lib/cjs/activities/upload/factory.js +25 -9
- package/lib/cjs/apps/base/api/strava/api.js +13 -6
- package/lib/cjs/apps/service.js +5 -2
- package/lib/cjs/apps/strava/StravaAppConnection.js +1 -3
- package/lib/cjs/devices/ride/service.js +9 -0
- package/lib/esm/activities/list/utils.js +16 -14
- package/lib/esm/activities/upload/factory.js +25 -9
- package/lib/esm/apps/base/api/strava/api.js +13 -6
- package/lib/esm/apps/service.js +5 -2
- package/lib/esm/apps/strava/StravaAppConnection.js +1 -3
- package/lib/esm/devices/ride/service.js +9 -0
- package/lib/types/activities/upload/factory.d.ts +2 -0
- package/lib/types/apps/base/api/strava/api.d.ts +1 -0
- package/lib/types/apps/base/api/strava/types.d.ts +0 -3
- package/lib/types/devices/ride/service.d.ts +1 -0
- package/package.json +1 -1
|
@@ -2,6 +2,12 @@
|
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports._createUIActivityDetails = exports.createUIActivityDetails = exports.createUIActivitySummary = exports.createUIActivityInfo = void 0;
|
|
4
4
|
const i18n_1 = require("../../i18n");
|
|
5
|
+
const formatOrUndefined = (value, dimension, C, U, digits) => {
|
|
6
|
+
const converted = C(value, dimension, { digits });
|
|
7
|
+
if (converted === undefined)
|
|
8
|
+
return undefined;
|
|
9
|
+
return { value: converted, unit: U(dimension) };
|
|
10
|
+
};
|
|
5
11
|
const createUIActivityInfo = (a) => {
|
|
6
12
|
if (!a)
|
|
7
13
|
return a;
|
|
@@ -17,10 +23,10 @@ const createUIActivitySummary = (summary) => {
|
|
|
17
23
|
return summary;
|
|
18
24
|
const ui = { ...summary };
|
|
19
25
|
const [C, U] = (0, i18n_1.getUnitConversionShortcuts)();
|
|
20
|
-
ui.distance =
|
|
21
|
-
if (ui.distance.value > 100)
|
|
26
|
+
ui.distance = formatOrUndefined(summary.distance, 'distance', C, U, 1);
|
|
27
|
+
if (ui.distance !== undefined && ui.distance.value > 100)
|
|
22
28
|
ui.distance.value = Math.round(ui.distance.value);
|
|
23
|
-
ui.totalElevation =
|
|
29
|
+
ui.totalElevation = formatOrUndefined(summary.totalElevation, 'elevation', C, U, 0);
|
|
24
30
|
return ui;
|
|
25
31
|
};
|
|
26
32
|
exports.createUIActivitySummary = createUIActivitySummary;
|
|
@@ -29,9 +35,7 @@ const createUIActivityDetails = (details) => {
|
|
|
29
35
|
return details;
|
|
30
36
|
const ui = { ...details };
|
|
31
37
|
const [C, U] = (0, i18n_1.getUnitConversionShortcuts)();
|
|
32
|
-
const formatSpeed = (v) =>
|
|
33
|
-
return { value: C(v, 'speed', { digits: 1 }), unit: U('speed') };
|
|
34
|
-
};
|
|
38
|
+
const formatSpeed = (v) => formatOrUndefined(v, 'speed', C, U, 1);
|
|
35
39
|
if (details.stats?.speed) {
|
|
36
40
|
ui.stats = {
|
|
37
41
|
...details.stats,
|
|
@@ -42,8 +46,8 @@ const createUIActivityDetails = (details) => {
|
|
|
42
46
|
ui.stats.speed[field] = formatSpeed(ui.stats.speed[field]);
|
|
43
47
|
}
|
|
44
48
|
}
|
|
45
|
-
ui.distance =
|
|
46
|
-
ui.totalElevation =
|
|
49
|
+
ui.distance = formatOrUndefined(details.distance, 'distance', C, U, 1);
|
|
50
|
+
ui.totalElevation = formatOrUndefined(details.totalElevation, 'elevation', C, U, 0);
|
|
47
51
|
ui.logs = (details.logs ?? []).map(log => {
|
|
48
52
|
const { speed, distance, elevation } = log;
|
|
49
53
|
return {
|
|
@@ -61,13 +65,11 @@ const _createUIActivityDetails = (details) => {
|
|
|
61
65
|
return details;
|
|
62
66
|
const ui = structuredClone(details);
|
|
63
67
|
const [C, U] = (0, i18n_1.getUnitConversionShortcuts)();
|
|
64
|
-
ui.distance =
|
|
65
|
-
if (ui.distance.value > 100)
|
|
68
|
+
ui.distance = formatOrUndefined(details.distance, 'distance', C, U, 1);
|
|
69
|
+
if (ui.distance !== undefined && ui.distance.value > 100)
|
|
66
70
|
ui.distance.value = Math.round(ui.distance.value);
|
|
67
|
-
ui.totalElevation =
|
|
68
|
-
const formatSpeed = (v) =>
|
|
69
|
-
return { value: C(v, 'speed', { digits: 1 }), unit: U('speed') };
|
|
70
|
-
};
|
|
71
|
+
ui.totalElevation = formatOrUndefined(details.totalElevation, 'elevation', C, U, 0);
|
|
72
|
+
const formatSpeed = (v) => formatOrUndefined(v, 'speed', C, U, 1);
|
|
71
73
|
if (ui.stats?.speed) {
|
|
72
74
|
const fields = ['min', 'max', 'avg'];
|
|
73
75
|
for (const field of fields) {
|
|
@@ -1,4 +1,11 @@
|
|
|
1
1
|
"use strict";
|
|
2
|
+
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
3
|
+
var useValue = arguments.length > 2;
|
|
4
|
+
for (var i = 0; i < initializers.length; i++) {
|
|
5
|
+
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
6
|
+
}
|
|
7
|
+
return useValue ? value : void 0;
|
|
8
|
+
};
|
|
2
9
|
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
3
10
|
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
4
11
|
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
@@ -26,31 +33,30 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
26
33
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
27
34
|
done = true;
|
|
28
35
|
};
|
|
29
|
-
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
30
|
-
var useValue = arguments.length > 2;
|
|
31
|
-
for (var i = 0; i < initializers.length; i++) {
|
|
32
|
-
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
33
|
-
}
|
|
34
|
-
return useValue ? value : void 0;
|
|
35
|
-
};
|
|
36
36
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
37
|
exports.ActivityUploadFactory = void 0;
|
|
38
38
|
const types_1 = require("../../base/types");
|
|
39
|
+
const Injection_1 = require("../../base/decorators/Injection");
|
|
40
|
+
const apps_1 = require("../../apps");
|
|
39
41
|
let ActivityUploadFactory = (() => {
|
|
40
42
|
let _classDecorators = [types_1.Singleton];
|
|
41
43
|
let _classDescriptor;
|
|
42
44
|
let _classExtraInitializers = [];
|
|
43
45
|
let _classThis;
|
|
46
|
+
let _instanceExtraInitializers = [];
|
|
47
|
+
let _getAppsService_decorators;
|
|
44
48
|
var ActivityUploadFactory = class {
|
|
45
49
|
static { _classThis = this; }
|
|
46
50
|
static {
|
|
47
51
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
52
|
+
_getAppsService_decorators = [Injection_1.Injectable];
|
|
53
|
+
__esDecorate(this, null, _getAppsService_decorators, { kind: "method", name: "getAppsService", static: false, private: false, access: { has: obj => "getAppsService" in obj, get: obj => obj.getAppsService }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
48
54
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
49
55
|
ActivityUploadFactory = _classThis = _classDescriptor.value;
|
|
50
56
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
51
57
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
52
58
|
}
|
|
53
|
-
uploaders;
|
|
59
|
+
uploaders = __runInitializers(this, _instanceExtraInitializers);
|
|
54
60
|
constructor() {
|
|
55
61
|
this.uploaders = [];
|
|
56
62
|
}
|
|
@@ -72,7 +78,7 @@ let ActivityUploadFactory = (() => {
|
|
|
72
78
|
const uploads = [];
|
|
73
79
|
this.uploaders.forEach(ui => {
|
|
74
80
|
const { service, uploader } = ui;
|
|
75
|
-
if (uploader.isConnected()) {
|
|
81
|
+
if (uploader.isConnected() && this.getAppsService().isEnabled(service, 'ActivityUpload')) {
|
|
76
82
|
const promise = uploader.upload(activity, format)
|
|
77
83
|
.then(success => ({ service, success }))
|
|
78
84
|
.catch(err => ({ service, success: false, error: err.message }));
|
|
@@ -87,6 +93,16 @@ let ActivityUploadFactory = (() => {
|
|
|
87
93
|
else
|
|
88
94
|
return [];
|
|
89
95
|
}
|
|
96
|
+
isUploadEnabled(service) {
|
|
97
|
+
const requested = this.uploaders.find(ui => ui.service === service);
|
|
98
|
+
if (!requested)
|
|
99
|
+
return false;
|
|
100
|
+
const uploader = requested.uploader;
|
|
101
|
+
return (uploader.isConnected() && this.getAppsService().isEnabled(service, 'ActivityUpload'));
|
|
102
|
+
}
|
|
103
|
+
getAppsService() {
|
|
104
|
+
return (0, apps_1.useAppsService)();
|
|
105
|
+
}
|
|
90
106
|
};
|
|
91
107
|
return ActivityUploadFactory = _classThis;
|
|
92
108
|
})();
|
|
@@ -9,6 +9,7 @@ const gd_eventlog_1 = require("gd-eventlog");
|
|
|
9
9
|
const sleep_1 = require("../../../../utils/sleep");
|
|
10
10
|
const API_BASE_URL = 'https://www.strava.com/api/v3';
|
|
11
11
|
const OAUTH_URL = 'https://www.strava.com/oauth';
|
|
12
|
+
const AUTH_SERVER_URL = 'https://auth.incyclist.com';
|
|
12
13
|
class StravaApi extends base_1.AppApiBase {
|
|
13
14
|
config;
|
|
14
15
|
logger;
|
|
@@ -158,16 +159,14 @@ class StravaApi extends base_1.AppApiBase {
|
|
|
158
159
|
async refreshToken() {
|
|
159
160
|
this.logger.logEvent({ message: 'Strava refresh Token start' });
|
|
160
161
|
let requestData;
|
|
162
|
+
const url = this.getAuthServerUrl() + '/strava/refresh';
|
|
161
163
|
try {
|
|
162
164
|
requestData = {
|
|
163
|
-
|
|
164
|
-
refresh_token: this.config.refreshToken,
|
|
165
|
-
client_secret: this.config.clientSecret,
|
|
166
|
-
client_id: this.config.clientId
|
|
165
|
+
refresh_token: this.config.refreshToken
|
|
167
166
|
};
|
|
168
167
|
const response = await this.getApi().request({
|
|
169
168
|
method: 'post',
|
|
170
|
-
url
|
|
169
|
+
url,
|
|
171
170
|
data: requestData
|
|
172
171
|
});
|
|
173
172
|
this.logger.logEvent({ message: 'Strava refresh Token result', status: 'success' });
|
|
@@ -182,7 +181,7 @@ class StravaApi extends base_1.AppApiBase {
|
|
|
182
181
|
let errorStr = err.message;
|
|
183
182
|
if (err.response) {
|
|
184
183
|
const { response } = err;
|
|
185
|
-
errorStr = `HTTP error ${response.status}: ${response.statusText}, url:${
|
|
184
|
+
errorStr = `HTTP error ${response.status}: ${response.statusText}, url:${url}, data:${JSON.stringify(requestData)}`;
|
|
186
185
|
}
|
|
187
186
|
this.logger.logEvent({ message: 'Strava refresh Token result', status: 'error', error: errorStr });
|
|
188
187
|
}
|
|
@@ -209,6 +208,14 @@ class StravaApi extends base_1.AppApiBase {
|
|
|
209
208
|
return OAUTH_URL;
|
|
210
209
|
}
|
|
211
210
|
}
|
|
211
|
+
getAuthServerUrl() {
|
|
212
|
+
try {
|
|
213
|
+
return this.getUserSettings().get('STRAVA_AUTH_SERVER_URL', AUTH_SERVER_URL);
|
|
214
|
+
}
|
|
215
|
+
catch {
|
|
216
|
+
return AUTH_SERVER_URL;
|
|
217
|
+
}
|
|
218
|
+
}
|
|
212
219
|
getBaseUrl() {
|
|
213
220
|
try {
|
|
214
221
|
return this.getUserSettings().get('STRAVA_API', API_BASE_URL);
|
package/lib/cjs/apps/service.js
CHANGED
|
@@ -145,10 +145,13 @@ let AppsService = (() => {
|
|
|
145
145
|
getConnectedServices(operation) {
|
|
146
146
|
const available = this.services[operation];
|
|
147
147
|
if (operation === 'ActivityUpload') {
|
|
148
|
-
const
|
|
148
|
+
const factory = this.getActivityUploadFactory();
|
|
149
|
+
const uploaders = available.map(a => factory.get(a));
|
|
149
150
|
const connected = uploaders.map((u, idx) => ({ connected: u?.isConnected(), key: available[idx] }))
|
|
150
151
|
.filter(s => s.connected);
|
|
151
|
-
|
|
152
|
+
const enabled = connected
|
|
153
|
+
.filter(s => factory.isUploadEnabled(s.key));
|
|
154
|
+
return this.serviceMap.filter(s => enabled.find(c => c.key === s.key));
|
|
152
155
|
}
|
|
153
156
|
else if (operation === 'WorkoutDownload') {
|
|
154
157
|
return this.serviceMap.filter(s => available.includes(s.key) && s.connection.isConnected());
|
|
@@ -123,9 +123,7 @@ let StravaAppConnection = (() => {
|
|
|
123
123
|
let isInitialized;
|
|
124
124
|
try {
|
|
125
125
|
const auth = this.getCredentials();
|
|
126
|
-
|
|
127
|
-
const clientSecret = this.getSecret('STRAVA_CLIENT_SECRET');
|
|
128
|
-
if (clientId && clientSecret && auth) {
|
|
126
|
+
if (auth) {
|
|
129
127
|
this.logEvent({ message: 'Strava init done', hasCredentials: true });
|
|
130
128
|
this.config = this.buildConfigFromCredentials(auth);
|
|
131
129
|
this.initApi(this.config);
|
|
@@ -50,6 +50,7 @@ const service_2 = require("../../base/service");
|
|
|
50
50
|
const types_1 = require("../../base/types");
|
|
51
51
|
const Injection_1 = require("../../base/decorators/Injection");
|
|
52
52
|
const apps_1 = require("../../apps");
|
|
53
|
+
const workouts_1 = require("../../workouts");
|
|
53
54
|
const NO_DATA_THRESHOLD = 10000;
|
|
54
55
|
const UNHEALTHY_THRESHOLD = 60000;
|
|
55
56
|
let DeviceRideService = (() => {
|
|
@@ -63,6 +64,7 @@ let DeviceRideService = (() => {
|
|
|
63
64
|
let _getUserSettings_decorators;
|
|
64
65
|
let _getDeviceAccess_decorators;
|
|
65
66
|
let _getGoogleMaps_decorators;
|
|
67
|
+
let _getWorkoutList_decorators;
|
|
66
68
|
var DeviceRideService = class extends _classSuper {
|
|
67
69
|
static { _classThis = this; }
|
|
68
70
|
static {
|
|
@@ -71,10 +73,12 @@ let DeviceRideService = (() => {
|
|
|
71
73
|
_getUserSettings_decorators = [Injection_1.Injectable];
|
|
72
74
|
_getDeviceAccess_decorators = [Injection_1.Injectable];
|
|
73
75
|
_getGoogleMaps_decorators = [Injection_1.Injectable];
|
|
76
|
+
_getWorkoutList_decorators = [Injection_1.Injectable];
|
|
74
77
|
__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);
|
|
75
78
|
__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);
|
|
76
79
|
__esDecorate(this, null, _getDeviceAccess_decorators, { kind: "method", name: "getDeviceAccess", static: false, private: false, access: { has: obj => "getDeviceAccess" in obj, get: obj => obj.getDeviceAccess }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
80
|
__esDecorate(this, null, _getGoogleMaps_decorators, { kind: "method", name: "getGoogleMaps", static: false, private: false, access: { has: obj => "getGoogleMaps" in obj, get: obj => obj.getGoogleMaps }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
81
|
+
__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);
|
|
78
82
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
79
83
|
DeviceRideService = _classThis = _classDescriptor.value;
|
|
80
84
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -1361,6 +1365,8 @@ let DeviceRideService = (() => {
|
|
|
1361
1365
|
}
|
|
1362
1366
|
canEnforceSimulator() {
|
|
1363
1367
|
const selected = (0, routes_1.getRouteList)().getSelected();
|
|
1368
|
+
if (this.getWorkoutList().getSelected() && !selected)
|
|
1369
|
+
return true;
|
|
1364
1370
|
const personalApiKey = this.getGoogleMaps().hasPersonalApiKey();
|
|
1365
1371
|
if (!selected?.description)
|
|
1366
1372
|
return false;
|
|
@@ -1416,6 +1422,9 @@ let DeviceRideService = (() => {
|
|
|
1416
1422
|
getGoogleMaps() {
|
|
1417
1423
|
return (0, apps_1.useGoogleMaps)();
|
|
1418
1424
|
}
|
|
1425
|
+
getWorkoutList() {
|
|
1426
|
+
return (0, workouts_1.useWorkoutList)();
|
|
1427
|
+
}
|
|
1419
1428
|
};
|
|
1420
1429
|
return DeviceRideService = _classThis;
|
|
1421
1430
|
})();
|
|
@@ -1,4 +1,10 @@
|
|
|
1
1
|
import { getUnitConversionShortcuts } from "../../i18n";
|
|
2
|
+
const formatOrUndefined = (value, dimension, C, U, digits) => {
|
|
3
|
+
const converted = C(value, dimension, { digits });
|
|
4
|
+
if (converted === undefined)
|
|
5
|
+
return undefined;
|
|
6
|
+
return { value: converted, unit: U(dimension) };
|
|
7
|
+
};
|
|
2
8
|
export const createUIActivityInfo = (a) => {
|
|
3
9
|
if (!a)
|
|
4
10
|
return a;
|
|
@@ -13,10 +19,10 @@ export const createUIActivitySummary = (summary) => {
|
|
|
13
19
|
return summary;
|
|
14
20
|
const ui = { ...summary };
|
|
15
21
|
const [C, U] = getUnitConversionShortcuts();
|
|
16
|
-
ui.distance =
|
|
17
|
-
if (ui.distance.value > 100)
|
|
22
|
+
ui.distance = formatOrUndefined(summary.distance, 'distance', C, U, 1);
|
|
23
|
+
if (ui.distance !== undefined && ui.distance.value > 100)
|
|
18
24
|
ui.distance.value = Math.round(ui.distance.value);
|
|
19
|
-
ui.totalElevation =
|
|
25
|
+
ui.totalElevation = formatOrUndefined(summary.totalElevation, 'elevation', C, U, 0);
|
|
20
26
|
return ui;
|
|
21
27
|
};
|
|
22
28
|
export const createUIActivityDetails = (details) => {
|
|
@@ -24,9 +30,7 @@ export const createUIActivityDetails = (details) => {
|
|
|
24
30
|
return details;
|
|
25
31
|
const ui = { ...details };
|
|
26
32
|
const [C, U] = getUnitConversionShortcuts();
|
|
27
|
-
const formatSpeed = (v) =>
|
|
28
|
-
return { value: C(v, 'speed', { digits: 1 }), unit: U('speed') };
|
|
29
|
-
};
|
|
33
|
+
const formatSpeed = (v) => formatOrUndefined(v, 'speed', C, U, 1);
|
|
30
34
|
if (details.stats?.speed) {
|
|
31
35
|
ui.stats = {
|
|
32
36
|
...details.stats,
|
|
@@ -37,8 +41,8 @@ export const createUIActivityDetails = (details) => {
|
|
|
37
41
|
ui.stats.speed[field] = formatSpeed(ui.stats.speed[field]);
|
|
38
42
|
}
|
|
39
43
|
}
|
|
40
|
-
ui.distance =
|
|
41
|
-
ui.totalElevation =
|
|
44
|
+
ui.distance = formatOrUndefined(details.distance, 'distance', C, U, 1);
|
|
45
|
+
ui.totalElevation = formatOrUndefined(details.totalElevation, 'elevation', C, U, 0);
|
|
42
46
|
ui.logs = (details.logs ?? []).map(log => {
|
|
43
47
|
const { speed, distance, elevation } = log;
|
|
44
48
|
return {
|
|
@@ -55,13 +59,11 @@ export const _createUIActivityDetails = (details) => {
|
|
|
55
59
|
return details;
|
|
56
60
|
const ui = structuredClone(details);
|
|
57
61
|
const [C, U] = getUnitConversionShortcuts();
|
|
58
|
-
ui.distance =
|
|
59
|
-
if (ui.distance.value > 100)
|
|
62
|
+
ui.distance = formatOrUndefined(details.distance, 'distance', C, U, 1);
|
|
63
|
+
if (ui.distance !== undefined && ui.distance.value > 100)
|
|
60
64
|
ui.distance.value = Math.round(ui.distance.value);
|
|
61
|
-
ui.totalElevation =
|
|
62
|
-
const formatSpeed = (v) =>
|
|
63
|
-
return { value: C(v, 'speed', { digits: 1 }), unit: U('speed') };
|
|
64
|
-
};
|
|
65
|
+
ui.totalElevation = formatOrUndefined(details.totalElevation, 'elevation', C, U, 0);
|
|
66
|
+
const formatSpeed = (v) => formatOrUndefined(v, 'speed', C, U, 1);
|
|
65
67
|
if (ui.stats?.speed) {
|
|
66
68
|
const fields = ['min', 'max', 'avg'];
|
|
67
69
|
for (const field of fields) {
|
|
@@ -1,3 +1,10 @@
|
|
|
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
|
+
};
|
|
1
8
|
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
2
9
|
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
3
10
|
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
@@ -25,29 +32,28 @@ var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn,
|
|
|
25
32
|
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
26
33
|
done = true;
|
|
27
34
|
};
|
|
28
|
-
var __runInitializers = (this && this.__runInitializers) || function (thisArg, initializers, value) {
|
|
29
|
-
var useValue = arguments.length > 2;
|
|
30
|
-
for (var i = 0; i < initializers.length; i++) {
|
|
31
|
-
value = useValue ? initializers[i].call(thisArg, value) : initializers[i].call(thisArg);
|
|
32
|
-
}
|
|
33
|
-
return useValue ? value : void 0;
|
|
34
|
-
};
|
|
35
35
|
import { Singleton } from "../../base/types";
|
|
36
|
+
import { Injectable } from "../../base/decorators/Injection";
|
|
37
|
+
import { useAppsService } from "../../apps";
|
|
36
38
|
let ActivityUploadFactory = (() => {
|
|
37
39
|
let _classDecorators = [Singleton];
|
|
38
40
|
let _classDescriptor;
|
|
39
41
|
let _classExtraInitializers = [];
|
|
40
42
|
let _classThis;
|
|
43
|
+
let _instanceExtraInitializers = [];
|
|
44
|
+
let _getAppsService_decorators;
|
|
41
45
|
var ActivityUploadFactory = class {
|
|
42
46
|
static { _classThis = this; }
|
|
43
47
|
static {
|
|
44
48
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
49
|
+
_getAppsService_decorators = [Injectable];
|
|
50
|
+
__esDecorate(this, null, _getAppsService_decorators, { kind: "method", name: "getAppsService", static: false, private: false, access: { has: obj => "getAppsService" in obj, get: obj => obj.getAppsService }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
45
51
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
46
52
|
ActivityUploadFactory = _classThis = _classDescriptor.value;
|
|
47
53
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
48
54
|
__runInitializers(_classThis, _classExtraInitializers);
|
|
49
55
|
}
|
|
50
|
-
uploaders;
|
|
56
|
+
uploaders = __runInitializers(this, _instanceExtraInitializers);
|
|
51
57
|
constructor() {
|
|
52
58
|
this.uploaders = [];
|
|
53
59
|
}
|
|
@@ -69,7 +75,7 @@ let ActivityUploadFactory = (() => {
|
|
|
69
75
|
const uploads = [];
|
|
70
76
|
this.uploaders.forEach(ui => {
|
|
71
77
|
const { service, uploader } = ui;
|
|
72
|
-
if (uploader.isConnected()) {
|
|
78
|
+
if (uploader.isConnected() && this.getAppsService().isEnabled(service, 'ActivityUpload')) {
|
|
73
79
|
const promise = uploader.upload(activity, format)
|
|
74
80
|
.then(success => ({ service, success }))
|
|
75
81
|
.catch(err => ({ service, success: false, error: err.message }));
|
|
@@ -84,6 +90,16 @@ let ActivityUploadFactory = (() => {
|
|
|
84
90
|
else
|
|
85
91
|
return [];
|
|
86
92
|
}
|
|
93
|
+
isUploadEnabled(service) {
|
|
94
|
+
const requested = this.uploaders.find(ui => ui.service === service);
|
|
95
|
+
if (!requested)
|
|
96
|
+
return false;
|
|
97
|
+
const uploader = requested.uploader;
|
|
98
|
+
return (uploader.isConnected() && this.getAppsService().isEnabled(service, 'ActivityUpload'));
|
|
99
|
+
}
|
|
100
|
+
getAppsService() {
|
|
101
|
+
return useAppsService();
|
|
102
|
+
}
|
|
87
103
|
};
|
|
88
104
|
return ActivityUploadFactory = _classThis;
|
|
89
105
|
})();
|
|
@@ -6,6 +6,7 @@ import { EventLogger } from 'gd-eventlog';
|
|
|
6
6
|
import { sleep } from "../../../../utils/sleep";
|
|
7
7
|
const API_BASE_URL = 'https://www.strava.com/api/v3';
|
|
8
8
|
const OAUTH_URL = 'https://www.strava.com/oauth';
|
|
9
|
+
const AUTH_SERVER_URL = 'https://auth.incyclist.com';
|
|
9
10
|
export class StravaApi extends AppApiBase {
|
|
10
11
|
config;
|
|
11
12
|
logger;
|
|
@@ -155,16 +156,14 @@ export class StravaApi extends AppApiBase {
|
|
|
155
156
|
async refreshToken() {
|
|
156
157
|
this.logger.logEvent({ message: 'Strava refresh Token start' });
|
|
157
158
|
let requestData;
|
|
159
|
+
const url = this.getAuthServerUrl() + '/strava/refresh';
|
|
158
160
|
try {
|
|
159
161
|
requestData = {
|
|
160
|
-
|
|
161
|
-
refresh_token: this.config.refreshToken,
|
|
162
|
-
client_secret: this.config.clientSecret,
|
|
163
|
-
client_id: this.config.clientId
|
|
162
|
+
refresh_token: this.config.refreshToken
|
|
164
163
|
};
|
|
165
164
|
const response = await this.getApi().request({
|
|
166
165
|
method: 'post',
|
|
167
|
-
url
|
|
166
|
+
url,
|
|
168
167
|
data: requestData
|
|
169
168
|
});
|
|
170
169
|
this.logger.logEvent({ message: 'Strava refresh Token result', status: 'success' });
|
|
@@ -179,7 +178,7 @@ export class StravaApi extends AppApiBase {
|
|
|
179
178
|
let errorStr = err.message;
|
|
180
179
|
if (err.response) {
|
|
181
180
|
const { response } = err;
|
|
182
|
-
errorStr = `HTTP error ${response.status}: ${response.statusText}, url:${
|
|
181
|
+
errorStr = `HTTP error ${response.status}: ${response.statusText}, url:${url}, data:${JSON.stringify(requestData)}`;
|
|
183
182
|
}
|
|
184
183
|
this.logger.logEvent({ message: 'Strava refresh Token result', status: 'error', error: errorStr });
|
|
185
184
|
}
|
|
@@ -206,6 +205,14 @@ export class StravaApi extends AppApiBase {
|
|
|
206
205
|
return OAUTH_URL;
|
|
207
206
|
}
|
|
208
207
|
}
|
|
208
|
+
getAuthServerUrl() {
|
|
209
|
+
try {
|
|
210
|
+
return this.getUserSettings().get('STRAVA_AUTH_SERVER_URL', AUTH_SERVER_URL);
|
|
211
|
+
}
|
|
212
|
+
catch {
|
|
213
|
+
return AUTH_SERVER_URL;
|
|
214
|
+
}
|
|
215
|
+
}
|
|
209
216
|
getBaseUrl() {
|
|
210
217
|
try {
|
|
211
218
|
return this.getUserSettings().get('STRAVA_API', API_BASE_URL);
|
package/lib/esm/apps/service.js
CHANGED
|
@@ -142,10 +142,13 @@ let AppsService = (() => {
|
|
|
142
142
|
getConnectedServices(operation) {
|
|
143
143
|
const available = this.services[operation];
|
|
144
144
|
if (operation === 'ActivityUpload') {
|
|
145
|
-
const
|
|
145
|
+
const factory = this.getActivityUploadFactory();
|
|
146
|
+
const uploaders = available.map(a => factory.get(a));
|
|
146
147
|
const connected = uploaders.map((u, idx) => ({ connected: u?.isConnected(), key: available[idx] }))
|
|
147
148
|
.filter(s => s.connected);
|
|
148
|
-
|
|
149
|
+
const enabled = connected
|
|
150
|
+
.filter(s => factory.isUploadEnabled(s.key));
|
|
151
|
+
return this.serviceMap.filter(s => enabled.find(c => c.key === s.key));
|
|
149
152
|
}
|
|
150
153
|
else if (operation === 'WorkoutDownload') {
|
|
151
154
|
return this.serviceMap.filter(s => available.includes(s.key) && s.connection.isConnected());
|
|
@@ -120,9 +120,7 @@ let StravaAppConnection = (() => {
|
|
|
120
120
|
let isInitialized;
|
|
121
121
|
try {
|
|
122
122
|
const auth = this.getCredentials();
|
|
123
|
-
|
|
124
|
-
const clientSecret = this.getSecret('STRAVA_CLIENT_SECRET');
|
|
125
|
-
if (clientId && clientSecret && auth) {
|
|
123
|
+
if (auth) {
|
|
126
124
|
this.logEvent({ message: 'Strava init done', hasCredentials: true });
|
|
127
125
|
this.config = this.buildConfigFromCredentials(auth);
|
|
128
126
|
this.initApi(this.config);
|
|
@@ -44,6 +44,7 @@ import { IncyclistService } from "../../base/service";
|
|
|
44
44
|
import { Singleton } from "../../base/types";
|
|
45
45
|
import { Injectable } from "../../base/decorators/Injection";
|
|
46
46
|
import { useGoogleMaps } from "../../apps";
|
|
47
|
+
import { useWorkoutList } from "../../workouts";
|
|
47
48
|
const NO_DATA_THRESHOLD = 10000;
|
|
48
49
|
const UNHEALTHY_THRESHOLD = 60000;
|
|
49
50
|
let DeviceRideService = (() => {
|
|
@@ -57,6 +58,7 @@ let DeviceRideService = (() => {
|
|
|
57
58
|
let _getUserSettings_decorators;
|
|
58
59
|
let _getDeviceAccess_decorators;
|
|
59
60
|
let _getGoogleMaps_decorators;
|
|
61
|
+
let _getWorkoutList_decorators;
|
|
60
62
|
var DeviceRideService = class extends _classSuper {
|
|
61
63
|
static { _classThis = this; }
|
|
62
64
|
static {
|
|
@@ -65,10 +67,12 @@ let DeviceRideService = (() => {
|
|
|
65
67
|
_getUserSettings_decorators = [Injectable];
|
|
66
68
|
_getDeviceAccess_decorators = [Injectable];
|
|
67
69
|
_getGoogleMaps_decorators = [Injectable];
|
|
70
|
+
_getWorkoutList_decorators = [Injectable];
|
|
68
71
|
__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);
|
|
69
72
|
__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);
|
|
70
73
|
__esDecorate(this, null, _getDeviceAccess_decorators, { kind: "method", name: "getDeviceAccess", static: false, private: false, access: { has: obj => "getDeviceAccess" in obj, get: obj => obj.getDeviceAccess }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
71
74
|
__esDecorate(this, null, _getGoogleMaps_decorators, { kind: "method", name: "getGoogleMaps", static: false, private: false, access: { has: obj => "getGoogleMaps" in obj, get: obj => obj.getGoogleMaps }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
75
|
+
__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);
|
|
72
76
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
73
77
|
DeviceRideService = _classThis = _classDescriptor.value;
|
|
74
78
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -1355,6 +1359,8 @@ let DeviceRideService = (() => {
|
|
|
1355
1359
|
}
|
|
1356
1360
|
canEnforceSimulator() {
|
|
1357
1361
|
const selected = getRouteList().getSelected();
|
|
1362
|
+
if (this.getWorkoutList().getSelected() && !selected)
|
|
1363
|
+
return true;
|
|
1358
1364
|
const personalApiKey = this.getGoogleMaps().hasPersonalApiKey();
|
|
1359
1365
|
if (!selected?.description)
|
|
1360
1366
|
return false;
|
|
@@ -1410,6 +1416,9 @@ let DeviceRideService = (() => {
|
|
|
1410
1416
|
getGoogleMaps() {
|
|
1411
1417
|
return useGoogleMaps();
|
|
1412
1418
|
}
|
|
1419
|
+
getWorkoutList() {
|
|
1420
|
+
return useWorkoutList();
|
|
1421
|
+
}
|
|
1413
1422
|
};
|
|
1414
1423
|
return DeviceRideService = _classThis;
|
|
1415
1424
|
})();
|
|
@@ -36,5 +36,6 @@ export declare class StravaApi extends AppApiBase {
|
|
|
36
36
|
protected refreshToken(): Promise<void>;
|
|
37
37
|
protected get(url: string, config?: object): Promise<AxiosResponse>;
|
|
38
38
|
protected getOauthBaseUrl(): any;
|
|
39
|
+
protected getAuthServerUrl(): any;
|
|
39
40
|
protected getBaseUrl(): any;
|
|
40
41
|
}
|
|
@@ -135,6 +135,7 @@ export declare class DeviceRideService extends IncyclistService {
|
|
|
135
135
|
protected getUserSettings(): import("../../settings").UserSettingsService;
|
|
136
136
|
protected getDeviceAccess(): import("../access/service").DeviceAccessService;
|
|
137
137
|
protected getGoogleMaps(): import("../../apps").GoogleMapsService;
|
|
138
|
+
protected getWorkoutList(): import("../../workouts").WorkoutListService;
|
|
138
139
|
}
|
|
139
140
|
export declare const useDeviceRide: () => DeviceRideService;
|
|
140
141
|
export {};
|