incyclist-services 1.6.1 → 1.6.2
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/activities/list/service.js +30 -10
- package/lib/apps/base/api/strava/api.d.ts +1 -0
- package/lib/apps/base/api/strava/api.js +6 -1
- package/lib/devices/configuration/service.js +1 -1
- package/lib/ride/display/service.js +12 -6
- package/lib/ride/route/RLVDisplayService.d.ts +2 -0
- package/lib/ride/route/RLVDisplayService.js +10 -1
- package/lib/routes/list/service.d.ts +1 -0
- package/lib/routes/list/service.js +42 -0
- package/lib/video/VideoSyncHelper.js +9 -1
- package/package.json +2 -2
|
@@ -79,7 +79,7 @@ let ActivityListService = (() => {
|
|
|
79
79
|
preload(props) {
|
|
80
80
|
let preloadObserver = this.getPreloadObserver();
|
|
81
81
|
try {
|
|
82
|
-
if (
|
|
82
|
+
if (preloadObserver === undefined || preloadObserver === null) {
|
|
83
83
|
this.logEvent({ message: 'preload activity list' });
|
|
84
84
|
const promise = this.loadActivities();
|
|
85
85
|
preloadObserver = this.observers.preload = new observer_1.PromiseObserver(promise);
|
|
@@ -247,10 +247,17 @@ let ActivityListService = (() => {
|
|
|
247
247
|
if (!activity) {
|
|
248
248
|
return false;
|
|
249
249
|
}
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
250
|
+
return new Promise(done => {
|
|
251
|
+
const emitUpdate = (update) => __awaiter(this, void 0, void 0, function* () {
|
|
252
|
+
this.exports = yield this.selected.getExports();
|
|
253
|
+
this.emitSelected('updated');
|
|
254
|
+
if (update.status === 'done')
|
|
255
|
+
done(update.success);
|
|
256
|
+
});
|
|
257
|
+
const observer = new observer_1.Observer();
|
|
258
|
+
observer.on('export', emitUpdate);
|
|
259
|
+
activity.export(format, observer);
|
|
260
|
+
});
|
|
254
261
|
});
|
|
255
262
|
}
|
|
256
263
|
upload(connectedApp) {
|
|
@@ -259,11 +266,24 @@ let ActivityListService = (() => {
|
|
|
259
266
|
if (!activity) {
|
|
260
267
|
return false;
|
|
261
268
|
}
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
269
|
+
return new Promise(done => {
|
|
270
|
+
const emitUploadUpdate = (update) => {
|
|
271
|
+
if (connectedApp === update.connectedApp) {
|
|
272
|
+
this.emitSelected('updated');
|
|
273
|
+
if (update.status === 'done') {
|
|
274
|
+
done(update.success);
|
|
275
|
+
}
|
|
276
|
+
}
|
|
277
|
+
};
|
|
278
|
+
const emitExportUpdate = (update) => __awaiter(this, void 0, void 0, function* () {
|
|
279
|
+
this.exports = yield this.selected.getExports();
|
|
280
|
+
this.emitSelected('updated');
|
|
281
|
+
});
|
|
282
|
+
const observer = new observer_1.Observer();
|
|
283
|
+
observer.on('upload', emitUploadUpdate);
|
|
284
|
+
observer.on('export', emitExportUpdate);
|
|
285
|
+
activity.upload(connectedApp, observer);
|
|
286
|
+
});
|
|
267
287
|
});
|
|
268
288
|
}
|
|
269
289
|
openRoute() {
|
|
@@ -28,6 +28,7 @@ export declare class StravaApi extends AppApiBase {
|
|
|
28
28
|
protected verifyToken(): Promise<void>;
|
|
29
29
|
protected isTokenStillValid(): boolean;
|
|
30
30
|
protected verifyAuthentication(): Promise<void>;
|
|
31
|
+
protected waitForReady(): Promise<void>;
|
|
31
32
|
protected waitForUploadResponse(response: StravaUploadResponse): Promise<StravaUploadResult>;
|
|
32
33
|
protected createUpload(request: StravaUploadRequest): Promise<StravaUploadResponse>;
|
|
33
34
|
protected getUploadById(id: string): Promise<StravaUploadResponse>;
|
|
@@ -125,11 +125,16 @@ class StravaApi extends base_1.AppApiBase {
|
|
|
125
125
|
yield this.verifyToken();
|
|
126
126
|
});
|
|
127
127
|
}
|
|
128
|
+
waitForReady() {
|
|
129
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
130
|
+
yield (0, utils_1.sleep)(1000);
|
|
131
|
+
});
|
|
132
|
+
}
|
|
128
133
|
waitForUploadResponse(response) {
|
|
129
134
|
return __awaiter(this, void 0, void 0, function* () {
|
|
130
135
|
let data = response;
|
|
131
136
|
while (data.status !== 'Your activity is ready.' && !data.error) {
|
|
132
|
-
yield
|
|
137
|
+
yield this.waitForReady();
|
|
133
138
|
data = yield this.getUploadById(data.id_str);
|
|
134
139
|
}
|
|
135
140
|
if (data.error) {
|
|
@@ -391,7 +391,7 @@ let DeviceConfigurationService = (() => {
|
|
|
391
391
|
if (adapter.getSupportedCyclingModes) {
|
|
392
392
|
modes = adapter.getSupportedCyclingModes();
|
|
393
393
|
}
|
|
394
|
-
const options = modes.map(M =>
|
|
394
|
+
const options = modes.map(M => adapter.createMode(M));
|
|
395
395
|
mode = requestedMode || device.mode;
|
|
396
396
|
if (!mode) {
|
|
397
397
|
modeObj = adapter.getDefaultCyclingMode();
|
|
@@ -173,6 +173,9 @@ let RideDisplayService = (() => {
|
|
|
173
173
|
}
|
|
174
174
|
pause(requester = 'user') {
|
|
175
175
|
var _a, _b;
|
|
176
|
+
if (requester === 'device' && this.isResuming) {
|
|
177
|
+
return;
|
|
178
|
+
}
|
|
176
179
|
try {
|
|
177
180
|
if (this.state !== 'Active')
|
|
178
181
|
return;
|
|
@@ -198,10 +201,8 @@ let RideDisplayService = (() => {
|
|
|
198
201
|
this.state = 'Active';
|
|
199
202
|
this.getActivityRide().resume();
|
|
200
203
|
this.getWorkoutRide().resume();
|
|
201
|
-
this.
|
|
204
|
+
this.pauseReason = 'device';
|
|
202
205
|
(_b = this.observer) === null || _b === void 0 ? void 0 : _b.emit('state-update', this.state);
|
|
203
|
-
(0, utils_1.waitNextTick)().then(() => this.isResuming = false);
|
|
204
|
-
delete this.pauseReason;
|
|
205
206
|
}
|
|
206
207
|
catch (err) {
|
|
207
208
|
this.logError(err, 'resume');
|
|
@@ -545,10 +546,15 @@ let RideDisplayService = (() => {
|
|
|
545
546
|
const currentValues = this.getActivityRide().getCurrentValues();
|
|
546
547
|
if (!currentValues)
|
|
547
548
|
return;
|
|
548
|
-
if (currentValues.speed === 0) {
|
|
549
|
+
if (currentValues.speed === 0 && !this.isResuming) {
|
|
549
550
|
this.pause('device');
|
|
550
551
|
return;
|
|
551
552
|
}
|
|
553
|
+
if (currentValues.speed > 0 && this.isResuming) {
|
|
554
|
+
this.displayService.resume();
|
|
555
|
+
this.isResuming = false;
|
|
556
|
+
delete this.pauseReason;
|
|
557
|
+
}
|
|
552
558
|
this.getRideModeService().onActivityUpdate(data, currentValues);
|
|
553
559
|
this.observer.emit('data-update', data, currentValues);
|
|
554
560
|
}
|
|
@@ -591,7 +597,6 @@ let RideDisplayService = (() => {
|
|
|
591
597
|
}
|
|
592
598
|
}
|
|
593
599
|
onLapCompleted(oldLap, newLap) {
|
|
594
|
-
console.log('# lap completed', oldLap, newLap);
|
|
595
600
|
}
|
|
596
601
|
onRouteUpdated(route) {
|
|
597
602
|
this.getActivityRide().onRouteUpdate(route.points);
|
|
@@ -891,7 +896,7 @@ let RideDisplayService = (() => {
|
|
|
891
896
|
udid: d.udid,
|
|
892
897
|
isControl: d.isControl,
|
|
893
898
|
capabilities: d.capabilities,
|
|
894
|
-
status:
|
|
899
|
+
status: 'Starting'
|
|
895
900
|
}));
|
|
896
901
|
this.updateStartOverlay();
|
|
897
902
|
}
|
|
@@ -974,6 +979,7 @@ let RideDisplayService = (() => {
|
|
|
974
979
|
const pct = Math.round(completed / total * 100);
|
|
975
980
|
this.logEvent({ message: 'onDeviceStartStatusUpdate', pct });
|
|
976
981
|
startDevice.stateText = `uploading (${pct}%)`;
|
|
982
|
+
this.checkStartStatus();
|
|
977
983
|
}
|
|
978
984
|
onDeviceData(data, udid) {
|
|
979
985
|
this.deviceData = data;
|
|
@@ -35,11 +35,13 @@ export declare class RLVDisplayService extends RouteDisplayService {
|
|
|
35
35
|
protected infotext?: InfotextDisplayProps;
|
|
36
36
|
protected videosInitialized: boolean;
|
|
37
37
|
protected startTime: number;
|
|
38
|
+
protected isVideoPaused: boolean;
|
|
38
39
|
constructor();
|
|
39
40
|
initView(): void;
|
|
40
41
|
getOverlayProps(overlay: any, props: CurrentRideDisplayProps): OverlayDisplayProps;
|
|
41
42
|
protected addVideo(route: Route, isCurrent?: boolean, parent?: VideoState): Promise<void>;
|
|
42
43
|
pause(): void;
|
|
44
|
+
resume(): void;
|
|
43
45
|
getDisplayProperties(props: CurrentRideDisplayProps): RLVDisplayProps;
|
|
44
46
|
protected getInfotextDisplayProps(): InfotextDisplayProps;
|
|
45
47
|
protected checkFinishOptions(position: CurrentPosition): boolean;
|
|
@@ -62,6 +62,7 @@ let RLVDisplayService = (() => {
|
|
|
62
62
|
super();
|
|
63
63
|
this.currentVideo = __runInitializers(this, _instanceExtraInitializers);
|
|
64
64
|
this.videosInitialized = false;
|
|
65
|
+
this.isVideoPaused = false;
|
|
65
66
|
this.isInitialized = false;
|
|
66
67
|
}
|
|
67
68
|
initView() {
|
|
@@ -130,6 +131,12 @@ let RLVDisplayService = (() => {
|
|
|
130
131
|
pause() {
|
|
131
132
|
super.pause();
|
|
132
133
|
this.currentVideo.syncHelper.pause();
|
|
134
|
+
this.isVideoPaused = true;
|
|
135
|
+
}
|
|
136
|
+
resume() {
|
|
137
|
+
super.resume();
|
|
138
|
+
this.currentVideo.syncHelper.resume();
|
|
139
|
+
this.isVideoPaused = false;
|
|
133
140
|
}
|
|
134
141
|
getDisplayProperties(props) {
|
|
135
142
|
var _b, _c, _d, _e;
|
|
@@ -380,7 +387,9 @@ let RLVDisplayService = (() => {
|
|
|
380
387
|
super.onActivityUpdate(activityPos, data);
|
|
381
388
|
const offset = (_b = this.offset) !== null && _b !== void 0 ? _b : 0;
|
|
382
389
|
const { routeDistance, speed } = activityPos;
|
|
383
|
-
this.
|
|
390
|
+
if (!this.isVideoPaused) {
|
|
391
|
+
this.currentVideo.syncHelper.onActivityUpdate(routeDistance - offset, speed);
|
|
392
|
+
}
|
|
384
393
|
}
|
|
385
394
|
initVideoSource(video) {
|
|
386
395
|
var _b, _c;
|
|
@@ -176,6 +176,7 @@ export declare class RouteListService extends IncyclistService implements IRoute
|
|
|
176
176
|
private selectListForSource;
|
|
177
177
|
private addCustomList;
|
|
178
178
|
createPreview(descr: RouteInfo): Promise<unknown>;
|
|
179
|
+
protected checkExistingPreviewFiles(descr: RouteInfo): Promise<string | undefined>;
|
|
179
180
|
protected doCreatePreview(descr: RouteInfo): Promise<string>;
|
|
180
181
|
protected processPreviewQueue(): PromiseObserver<void>;
|
|
181
182
|
protected findCard(target: Route | string): {
|
|
@@ -993,6 +993,45 @@ let RouteListService = (() => {
|
|
|
993
993
|
});
|
|
994
994
|
});
|
|
995
995
|
}
|
|
996
|
+
checkExistingPreviewFiles(descr) {
|
|
997
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
998
|
+
var _a;
|
|
999
|
+
const videoUrl = descr.videoUrl || descr.downloadUrl;
|
|
1000
|
+
const path = (0, api_1.getBindings)().path;
|
|
1001
|
+
const fs = (0, api_1.getBindings)().fs;
|
|
1002
|
+
let existingPreview;
|
|
1003
|
+
let fileUrl = false;
|
|
1004
|
+
try {
|
|
1005
|
+
let { dir, name } = (_a = path.parse(videoUrl)) !== null && _a !== void 0 ? _a : {};
|
|
1006
|
+
if (!dir.startsWith('htttp')) {
|
|
1007
|
+
if (dir.startsWith('video:')) {
|
|
1008
|
+
dir = dir.replace('video:', 'file:');
|
|
1009
|
+
}
|
|
1010
|
+
if (dir.startsWith('file:///')) {
|
|
1011
|
+
dir = dir.replace('file:///', '');
|
|
1012
|
+
fileUrl = true;
|
|
1013
|
+
}
|
|
1014
|
+
const check = (name) => __awaiter(this, void 0, void 0, function* () {
|
|
1015
|
+
if (existingPreview)
|
|
1016
|
+
return;
|
|
1017
|
+
if (yield fs.existsFile(name))
|
|
1018
|
+
existingPreview = name;
|
|
1019
|
+
});
|
|
1020
|
+
yield check(path.join(dir, 'preview.png'));
|
|
1021
|
+
yield check(path.join(dir, 'preview.jpg'));
|
|
1022
|
+
yield check(path.join(dir, `${name}_preview.png`));
|
|
1023
|
+
yield check(path.join(dir, `${name}_preview.jpg`));
|
|
1024
|
+
if (existingPreview) {
|
|
1025
|
+
this.logEvent({ message: 'found preview', title: descr.title, id: descr.id, video: videoUrl, existingPreview });
|
|
1026
|
+
descr.previewUrl = fileUrl ? `file:///${existingPreview}` : existingPreview;
|
|
1027
|
+
return descr.previewUrl;
|
|
1028
|
+
}
|
|
1029
|
+
}
|
|
1030
|
+
}
|
|
1031
|
+
catch (_b) {
|
|
1032
|
+
}
|
|
1033
|
+
});
|
|
1034
|
+
}
|
|
996
1035
|
doCreatePreview(descr) {
|
|
997
1036
|
return __awaiter(this, void 0, void 0, function* () {
|
|
998
1037
|
let props;
|
|
@@ -1005,6 +1044,9 @@ let RouteListService = (() => {
|
|
|
1005
1044
|
const fs = (0, api_1.getBindings)().fs;
|
|
1006
1045
|
const outDir = path.join(appInfo.getAppDir(), 'previewImg');
|
|
1007
1046
|
yield fs.ensureDir(outDir);
|
|
1047
|
+
const existing = yield this.checkExistingPreviewFiles(descr);
|
|
1048
|
+
if (existing)
|
|
1049
|
+
return existing;
|
|
1008
1050
|
if (!videoUrl)
|
|
1009
1051
|
return;
|
|
1010
1052
|
if (videoUrl.startsWith('http')) {
|
|
@@ -24,12 +24,16 @@ class VideoSyncHelper extends service_1.IncyclistService {
|
|
|
24
24
|
this.logPlaybackSummary();
|
|
25
25
|
this.isPaused = true;
|
|
26
26
|
this.send('rate-update', 0);
|
|
27
|
+
this.activityStatus.ts = Date.now();
|
|
28
|
+
this.rlvStatus.ts = Date.now();
|
|
27
29
|
}
|
|
28
30
|
resume() {
|
|
29
31
|
if (this.isStopped)
|
|
30
32
|
return;
|
|
31
33
|
this.logEvent({ message: 'video resumed', route: this.route.details.title });
|
|
32
34
|
this.isPaused = false;
|
|
35
|
+
this.activityStatus.ts = Date.now();
|
|
36
|
+
this.rlvStatus.ts = Date.now();
|
|
33
37
|
}
|
|
34
38
|
reset() {
|
|
35
39
|
this.logEvent({ message: 'video reset', route: this.route.details.title });
|
|
@@ -64,7 +68,7 @@ class VideoSyncHelper extends service_1.IncyclistService {
|
|
|
64
68
|
try {
|
|
65
69
|
this.endTime = (_a = this.endTime) !== null && _a !== void 0 ? _a : this.getVideoTimeByPosition((_b = this.route.description) === null || _b === void 0 ? void 0 : _b.distance);
|
|
66
70
|
const endTime = this.endTime;
|
|
67
|
-
if (this.isStopped)
|
|
71
|
+
if (this.isStopped || this.isPaused)
|
|
68
72
|
return;
|
|
69
73
|
if (time > endTime - 0.3 && !this.loopMode && !this.rlvStatus.timeRequested) {
|
|
70
74
|
this.updateRate(0);
|
|
@@ -305,6 +309,10 @@ class VideoSyncHelper extends service_1.IncyclistService {
|
|
|
305
309
|
if (this.isPaused && rate > 0) {
|
|
306
310
|
this.resume();
|
|
307
311
|
}
|
|
312
|
+
else if (this.isPaused && rate === 0) {
|
|
313
|
+
delete this.rlvStatus.rateRequested;
|
|
314
|
+
return;
|
|
315
|
+
}
|
|
308
316
|
this.rlvStatus.rateRequested = rate;
|
|
309
317
|
this.send('rate-update', rate);
|
|
310
318
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "incyclist-services",
|
|
3
|
-
"version": "1.6.
|
|
3
|
+
"version": "1.6.2",
|
|
4
4
|
"peerDependencies": {
|
|
5
5
|
"gd-eventlog": "^0.1.26"
|
|
6
6
|
},
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
},
|
|
43
43
|
"dependencies": {
|
|
44
44
|
"axios": "^1.8.2",
|
|
45
|
-
"incyclist-devices": "^2.4.
|
|
45
|
+
"incyclist-devices": "^2.4.7",
|
|
46
46
|
"promise.any": "^2.0.6",
|
|
47
47
|
"semver": "^7.6.3",
|
|
48
48
|
"tcx-builder": "^1.1.1",
|