incyclist-services 1.7.88 → 1.7.89
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/appstate/index.js +1 -0
- package/lib/cjs/appstate/toggle-sync.js +174 -0
- package/lib/cjs/routes/list/loaders/types.js +1 -1
- package/lib/cjs/routes/list/service.js +2 -1
- package/lib/cjs/ui/service.js +7 -0
- package/lib/esm/appstate/index.js +1 -0
- package/lib/esm/appstate/toggle-sync.js +170 -0
- package/lib/esm/routes/list/loaders/types.js +1 -1
- package/lib/esm/routes/list/service.js +2 -1
- package/lib/esm/ui/service.js +8 -1
- package/lib/types/appstate/index.d.ts +1 -0
- package/lib/types/appstate/toggle-sync.d.ts +22 -0
- package/lib/types/ui/service.d.ts +1 -0
- package/package.json +1 -1
|
@@ -16,3 +16,4 @@ var __exportStar = (this && this.__exportStar) || function(m, exports) {
|
|
|
16
16
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
17
17
|
__exportStar(require("./service"), exports);
|
|
18
18
|
__exportStar(require("./types"), exports);
|
|
19
|
+
__exportStar(require("./toggle-sync"), exports);
|
|
@@ -0,0 +1,174 @@
|
|
|
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
|
+
};
|
|
9
|
+
var __esDecorate = (this && this.__esDecorate) || function (ctor, descriptorIn, decorators, contextIn, initializers, extraInitializers) {
|
|
10
|
+
function accept(f) { if (f !== void 0 && typeof f !== "function") throw new TypeError("Function expected"); return f; }
|
|
11
|
+
var kind = contextIn.kind, key = kind === "getter" ? "get" : kind === "setter" ? "set" : "value";
|
|
12
|
+
var target = !descriptorIn && ctor ? contextIn["static"] ? ctor : ctor.prototype : null;
|
|
13
|
+
var descriptor = descriptorIn || (target ? Object.getOwnPropertyDescriptor(target, contextIn.name) : {});
|
|
14
|
+
var _, done = false;
|
|
15
|
+
for (var i = decorators.length - 1; i >= 0; i--) {
|
|
16
|
+
var context = {};
|
|
17
|
+
for (var p in contextIn) context[p] = p === "access" ? {} : contextIn[p];
|
|
18
|
+
for (var p in contextIn.access) context.access[p] = contextIn.access[p];
|
|
19
|
+
context.addInitializer = function (f) { if (done) throw new TypeError("Cannot add initializers after decoration has completed"); extraInitializers.push(accept(f || null)); };
|
|
20
|
+
var result = (0, decorators[i])(kind === "accessor" ? { get: descriptor.get, set: descriptor.set } : descriptor[key], context);
|
|
21
|
+
if (kind === "accessor") {
|
|
22
|
+
if (result === void 0) continue;
|
|
23
|
+
if (result === null || typeof result !== "object") throw new TypeError("Object expected");
|
|
24
|
+
if (_ = accept(result.get)) descriptor.get = _;
|
|
25
|
+
if (_ = accept(result.set)) descriptor.set = _;
|
|
26
|
+
if (_ = accept(result.init)) initializers.unshift(_);
|
|
27
|
+
}
|
|
28
|
+
else if (_ = accept(result)) {
|
|
29
|
+
if (kind === "field") initializers.unshift(_);
|
|
30
|
+
else descriptor[key] = _;
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
if (target) Object.defineProperty(target, contextIn.name, descriptor);
|
|
34
|
+
done = true;
|
|
35
|
+
};
|
|
36
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
37
|
+
exports.useFeatureToggleSync = exports.FeatureToggleSyncService = void 0;
|
|
38
|
+
const api_1 = require("../api");
|
|
39
|
+
const decorators_1 = require("../base/decorators");
|
|
40
|
+
const service_1 = require("../base/service");
|
|
41
|
+
const singleton_1 = require("../base/types/singleton");
|
|
42
|
+
const settings_1 = require("../settings");
|
|
43
|
+
const TOPIC_PREFIX = 'incyclist/features';
|
|
44
|
+
let FeatureToggleSyncService = (() => {
|
|
45
|
+
let _classDecorators = [singleton_1.Singleton];
|
|
46
|
+
let _classDescriptor;
|
|
47
|
+
let _classExtraInitializers = [];
|
|
48
|
+
let _classThis;
|
|
49
|
+
let _classSuper = service_1.IncyclistService;
|
|
50
|
+
let _instanceExtraInitializers = [];
|
|
51
|
+
let _getMessageQueue_decorators;
|
|
52
|
+
let _getUserSettings_decorators;
|
|
53
|
+
var FeatureToggleSyncService = class extends _classSuper {
|
|
54
|
+
static { _classThis = this; }
|
|
55
|
+
static {
|
|
56
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
57
|
+
_getMessageQueue_decorators = [decorators_1.Injectable];
|
|
58
|
+
_getUserSettings_decorators = [decorators_1.Injectable];
|
|
59
|
+
__esDecorate(this, null, _getMessageQueue_decorators, { kind: "method", name: "getMessageQueue", static: false, private: false, access: { has: obj => "getMessageQueue" in obj, get: obj => obj.getMessageQueue }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
60
|
+
__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);
|
|
61
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
62
|
+
FeatureToggleSyncService = _classThis = _classDescriptor.value;
|
|
63
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
64
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
65
|
+
}
|
|
66
|
+
uuid = __runInitializers(this, _instanceExtraInitializers);
|
|
67
|
+
subscribed = false;
|
|
68
|
+
onMessageHandler = this.onMessage.bind(this);
|
|
69
|
+
constructor() {
|
|
70
|
+
super('FeatureToggleSync');
|
|
71
|
+
}
|
|
72
|
+
start(uuid) {
|
|
73
|
+
try {
|
|
74
|
+
if (!uuid)
|
|
75
|
+
return;
|
|
76
|
+
if (this.subscribed && this.uuid === uuid)
|
|
77
|
+
return;
|
|
78
|
+
if (this.subscribed)
|
|
79
|
+
this.stop();
|
|
80
|
+
const mq = this.getMessageQueue();
|
|
81
|
+
if (!mq?.enabled?.()) {
|
|
82
|
+
this.logEvent({ message: 'feature-toggle sync not started', reason: 'mq binding not enabled', uuid });
|
|
83
|
+
return;
|
|
84
|
+
}
|
|
85
|
+
this.uuid = uuid;
|
|
86
|
+
mq.on('mq-message', this.onMessageHandler);
|
|
87
|
+
mq.subscribe(this.getTopic(uuid));
|
|
88
|
+
this.subscribed = true;
|
|
89
|
+
this.logEvent({ message: 'feature-toggle sync started', uuid, topic: this.getTopic(uuid) });
|
|
90
|
+
}
|
|
91
|
+
catch (err) {
|
|
92
|
+
this.logError(err, 'start');
|
|
93
|
+
}
|
|
94
|
+
}
|
|
95
|
+
stop() {
|
|
96
|
+
try {
|
|
97
|
+
if (!this.subscribed)
|
|
98
|
+
return;
|
|
99
|
+
const mq = this.getMessageQueue();
|
|
100
|
+
if (mq) {
|
|
101
|
+
mq.off('mq-message', this.onMessageHandler);
|
|
102
|
+
if (this.uuid)
|
|
103
|
+
mq.unsubscribe(this.getTopic(this.uuid));
|
|
104
|
+
}
|
|
105
|
+
this.logEvent({ message: 'feature-toggle sync stopped', uuid: this.uuid });
|
|
106
|
+
}
|
|
107
|
+
catch (err) {
|
|
108
|
+
this.logError(err, 'stop');
|
|
109
|
+
}
|
|
110
|
+
finally {
|
|
111
|
+
this.subscribed = false;
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
getTopic(uuid) {
|
|
115
|
+
return `${TOPIC_PREFIX}/${uuid}/+`;
|
|
116
|
+
}
|
|
117
|
+
getTopicPrefix() {
|
|
118
|
+
return this.uuid ? `${TOPIC_PREFIX}/${this.uuid}/` : undefined;
|
|
119
|
+
}
|
|
120
|
+
onMessage(topic, message) {
|
|
121
|
+
try {
|
|
122
|
+
const prefix = this.getTopicPrefix();
|
|
123
|
+
if (!prefix || typeof topic !== 'string' || !topic.startsWith(prefix))
|
|
124
|
+
return;
|
|
125
|
+
const toggleName = this.parseToggleName(topic, prefix);
|
|
126
|
+
if (!toggleName) {
|
|
127
|
+
this.logEvent({ message: 'feature-toggle sync: ignoring malformed topic', topic, payload: message });
|
|
128
|
+
return;
|
|
129
|
+
}
|
|
130
|
+
const payload = this.parsePayload(message);
|
|
131
|
+
if (!payload || typeof payload.value !== 'boolean') {
|
|
132
|
+
this.logEvent({ message: 'feature-toggle sync: ignoring malformed payload', topic, payload: message });
|
|
133
|
+
return;
|
|
134
|
+
}
|
|
135
|
+
this.getUserSettings().set(toggleName, payload.value);
|
|
136
|
+
this.logEvent({ message: 'feature-toggle sync: applied toggle', toggle: toggleName, value: payload.value });
|
|
137
|
+
}
|
|
138
|
+
catch (err) {
|
|
139
|
+
this.logError(err, 'onMessage', { topic });
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
parseToggleName(topic, prefix) {
|
|
143
|
+
const toggleName = topic.slice(prefix.length);
|
|
144
|
+
if (!toggleName || toggleName.includes('/'))
|
|
145
|
+
return undefined;
|
|
146
|
+
return toggleName;
|
|
147
|
+
}
|
|
148
|
+
parsePayload(message) {
|
|
149
|
+
try {
|
|
150
|
+
let str;
|
|
151
|
+
if (typeof message === 'string')
|
|
152
|
+
str = message;
|
|
153
|
+
else if (message instanceof Uint8Array)
|
|
154
|
+
str = Buffer.from(message.buffer).toString();
|
|
155
|
+
else
|
|
156
|
+
return undefined;
|
|
157
|
+
return JSON.parse(str);
|
|
158
|
+
}
|
|
159
|
+
catch {
|
|
160
|
+
return undefined;
|
|
161
|
+
}
|
|
162
|
+
}
|
|
163
|
+
getMessageQueue() {
|
|
164
|
+
return (0, api_1.getBindings)().mq;
|
|
165
|
+
}
|
|
166
|
+
getUserSettings() {
|
|
167
|
+
return (0, settings_1.useUserSettings)();
|
|
168
|
+
}
|
|
169
|
+
};
|
|
170
|
+
return FeatureToggleSyncService = _classThis;
|
|
171
|
+
})();
|
|
172
|
+
exports.FeatureToggleSyncService = FeatureToggleSyncService;
|
|
173
|
+
const useFeatureToggleSync = () => new FeatureToggleSyncService();
|
|
174
|
+
exports.useFeatureToggleSync = useFeatureToggleSync;
|
|
@@ -8,7 +8,7 @@ const utils_2 = require("../../base/parsers/utils");
|
|
|
8
8
|
const route_1 = require("../../base/utils/route");
|
|
9
9
|
const MALFORMED_VIDEO_URL = /^video:\/{4,}/;
|
|
10
10
|
const correctVideoUrl = (url, isMobile = false) => {
|
|
11
|
-
if (!url
|
|
11
|
+
if (!url?.startsWith('video:'))
|
|
12
12
|
return undefined;
|
|
13
13
|
const malformed = MALFORMED_VIDEO_URL.test(url);
|
|
14
14
|
if (!malformed && !isMobile)
|
|
@@ -888,13 +888,14 @@ let RouteListService = (() => {
|
|
|
888
888
|
if (!route.description.country) {
|
|
889
889
|
route.updateCountryFromPoints()
|
|
890
890
|
.then(() => {
|
|
891
|
-
this.logEvent({ message: 'preload route updated
|
|
891
|
+
this.logEvent({ message: 'preload route updated', route: card?.getData()?.title, reason: 'country added' });
|
|
892
892
|
this.db.save(route, false);
|
|
893
893
|
});
|
|
894
894
|
}
|
|
895
895
|
if (route.description.hasVideo && route.description.isDownloaded) {
|
|
896
896
|
card.videoExists().then(exists => {
|
|
897
897
|
if (!exists) {
|
|
898
|
+
this.logEvent({ message: 'preload route updated', route: card?.getData()?.title, reason: 'downloaded file missing' });
|
|
898
899
|
card.resetDownload();
|
|
899
900
|
}
|
|
900
901
|
});
|
package/lib/cjs/ui/service.js
CHANGED
|
@@ -63,6 +63,7 @@ let UserInterfaceServcie = (() => {
|
|
|
63
63
|
let _getUserSettings_decorators;
|
|
64
64
|
let _getOnlineStatusMonitoring_decorators;
|
|
65
65
|
let _getAppState_decorators;
|
|
66
|
+
let _getFeatureToggleSync_decorators;
|
|
66
67
|
var UserInterfaceServcie = class extends _classSuper {
|
|
67
68
|
static { _classThis = this; }
|
|
68
69
|
static {
|
|
@@ -72,11 +73,13 @@ let UserInterfaceServcie = (() => {
|
|
|
72
73
|
_getUserSettings_decorators = [decorators_1.Injectable];
|
|
73
74
|
_getOnlineStatusMonitoring_decorators = [decorators_1.Injectable];
|
|
74
75
|
_getAppState_decorators = [decorators_1.Injectable];
|
|
76
|
+
_getFeatureToggleSync_decorators = [decorators_1.Injectable];
|
|
75
77
|
__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);
|
|
76
78
|
__esDecorate(this, null, _getMessageQueue_decorators, { kind: "method", name: "getMessageQueue", static: false, private: false, access: { has: obj => "getMessageQueue" in obj, get: obj => obj.getMessageQueue }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
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);
|
|
78
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);
|
|
79
81
|
__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);
|
|
82
|
+
__esDecorate(this, null, _getFeatureToggleSync_decorators, { kind: "method", name: "getFeatureToggleSync", static: false, private: false, access: { has: obj => "getFeatureToggleSync" in obj, get: obj => obj.getFeatureToggleSync }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
80
83
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
81
84
|
UserInterfaceServcie = _classThis = _classDescriptor.value;
|
|
82
85
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -208,6 +211,7 @@ let UserInterfaceServcie = (() => {
|
|
|
208
211
|
const sent = false;
|
|
209
212
|
const user = this.getUserSettings().getValue('user', {});
|
|
210
213
|
const id = this.getUserSettings().getValue('uuid', undefined);
|
|
214
|
+
this.getFeatureToggleSync().start(id);
|
|
211
215
|
const { username, weight, ftp, gender } = user;
|
|
212
216
|
const topic = `incyclist/session/${this.session}/start`;
|
|
213
217
|
const os = this.getBindings().appInfo?.getOS()?.platform;
|
|
@@ -500,6 +504,9 @@ let UserInterfaceServcie = (() => {
|
|
|
500
504
|
getAppState() {
|
|
501
505
|
return (0, appstate_1.useAppState)();
|
|
502
506
|
}
|
|
507
|
+
getFeatureToggleSync() {
|
|
508
|
+
return (0, appstate_1.useFeatureToggleSync)();
|
|
509
|
+
}
|
|
503
510
|
};
|
|
504
511
|
return UserInterfaceServcie = _classThis;
|
|
505
512
|
})();
|
|
@@ -0,0 +1,170 @@
|
|
|
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 { getBindings } from "../api";
|
|
36
|
+
import { Injectable } from "../base/decorators";
|
|
37
|
+
import { IncyclistService } from "../base/service";
|
|
38
|
+
import { Singleton } from "../base/types/singleton";
|
|
39
|
+
import { useUserSettings } from "../settings";
|
|
40
|
+
const TOPIC_PREFIX = 'incyclist/features';
|
|
41
|
+
let FeatureToggleSyncService = (() => {
|
|
42
|
+
let _classDecorators = [Singleton];
|
|
43
|
+
let _classDescriptor;
|
|
44
|
+
let _classExtraInitializers = [];
|
|
45
|
+
let _classThis;
|
|
46
|
+
let _classSuper = IncyclistService;
|
|
47
|
+
let _instanceExtraInitializers = [];
|
|
48
|
+
let _getMessageQueue_decorators;
|
|
49
|
+
let _getUserSettings_decorators;
|
|
50
|
+
var FeatureToggleSyncService = class extends _classSuper {
|
|
51
|
+
static { _classThis = this; }
|
|
52
|
+
static {
|
|
53
|
+
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(_classSuper[Symbol.metadata] ?? null) : void 0;
|
|
54
|
+
_getMessageQueue_decorators = [Injectable];
|
|
55
|
+
_getUserSettings_decorators = [Injectable];
|
|
56
|
+
__esDecorate(this, null, _getMessageQueue_decorators, { kind: "method", name: "getMessageQueue", static: false, private: false, access: { has: obj => "getMessageQueue" in obj, get: obj => obj.getMessageQueue }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
57
|
+
__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);
|
|
58
|
+
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
59
|
+
FeatureToggleSyncService = _classThis = _classDescriptor.value;
|
|
60
|
+
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
61
|
+
__runInitializers(_classThis, _classExtraInitializers);
|
|
62
|
+
}
|
|
63
|
+
uuid = __runInitializers(this, _instanceExtraInitializers);
|
|
64
|
+
subscribed = false;
|
|
65
|
+
onMessageHandler = this.onMessage.bind(this);
|
|
66
|
+
constructor() {
|
|
67
|
+
super('FeatureToggleSync');
|
|
68
|
+
}
|
|
69
|
+
start(uuid) {
|
|
70
|
+
try {
|
|
71
|
+
if (!uuid)
|
|
72
|
+
return;
|
|
73
|
+
if (this.subscribed && this.uuid === uuid)
|
|
74
|
+
return;
|
|
75
|
+
if (this.subscribed)
|
|
76
|
+
this.stop();
|
|
77
|
+
const mq = this.getMessageQueue();
|
|
78
|
+
if (!mq?.enabled?.()) {
|
|
79
|
+
this.logEvent({ message: 'feature-toggle sync not started', reason: 'mq binding not enabled', uuid });
|
|
80
|
+
return;
|
|
81
|
+
}
|
|
82
|
+
this.uuid = uuid;
|
|
83
|
+
mq.on('mq-message', this.onMessageHandler);
|
|
84
|
+
mq.subscribe(this.getTopic(uuid));
|
|
85
|
+
this.subscribed = true;
|
|
86
|
+
this.logEvent({ message: 'feature-toggle sync started', uuid, topic: this.getTopic(uuid) });
|
|
87
|
+
}
|
|
88
|
+
catch (err) {
|
|
89
|
+
this.logError(err, 'start');
|
|
90
|
+
}
|
|
91
|
+
}
|
|
92
|
+
stop() {
|
|
93
|
+
try {
|
|
94
|
+
if (!this.subscribed)
|
|
95
|
+
return;
|
|
96
|
+
const mq = this.getMessageQueue();
|
|
97
|
+
if (mq) {
|
|
98
|
+
mq.off('mq-message', this.onMessageHandler);
|
|
99
|
+
if (this.uuid)
|
|
100
|
+
mq.unsubscribe(this.getTopic(this.uuid));
|
|
101
|
+
}
|
|
102
|
+
this.logEvent({ message: 'feature-toggle sync stopped', uuid: this.uuid });
|
|
103
|
+
}
|
|
104
|
+
catch (err) {
|
|
105
|
+
this.logError(err, 'stop');
|
|
106
|
+
}
|
|
107
|
+
finally {
|
|
108
|
+
this.subscribed = false;
|
|
109
|
+
}
|
|
110
|
+
}
|
|
111
|
+
getTopic(uuid) {
|
|
112
|
+
return `${TOPIC_PREFIX}/${uuid}/+`;
|
|
113
|
+
}
|
|
114
|
+
getTopicPrefix() {
|
|
115
|
+
return this.uuid ? `${TOPIC_PREFIX}/${this.uuid}/` : undefined;
|
|
116
|
+
}
|
|
117
|
+
onMessage(topic, message) {
|
|
118
|
+
try {
|
|
119
|
+
const prefix = this.getTopicPrefix();
|
|
120
|
+
if (!prefix || typeof topic !== 'string' || !topic.startsWith(prefix))
|
|
121
|
+
return;
|
|
122
|
+
const toggleName = this.parseToggleName(topic, prefix);
|
|
123
|
+
if (!toggleName) {
|
|
124
|
+
this.logEvent({ message: 'feature-toggle sync: ignoring malformed topic', topic, payload: message });
|
|
125
|
+
return;
|
|
126
|
+
}
|
|
127
|
+
const payload = this.parsePayload(message);
|
|
128
|
+
if (!payload || typeof payload.value !== 'boolean') {
|
|
129
|
+
this.logEvent({ message: 'feature-toggle sync: ignoring malformed payload', topic, payload: message });
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
this.getUserSettings().set(toggleName, payload.value);
|
|
133
|
+
this.logEvent({ message: 'feature-toggle sync: applied toggle', toggle: toggleName, value: payload.value });
|
|
134
|
+
}
|
|
135
|
+
catch (err) {
|
|
136
|
+
this.logError(err, 'onMessage', { topic });
|
|
137
|
+
}
|
|
138
|
+
}
|
|
139
|
+
parseToggleName(topic, prefix) {
|
|
140
|
+
const toggleName = topic.slice(prefix.length);
|
|
141
|
+
if (!toggleName || toggleName.includes('/'))
|
|
142
|
+
return undefined;
|
|
143
|
+
return toggleName;
|
|
144
|
+
}
|
|
145
|
+
parsePayload(message) {
|
|
146
|
+
try {
|
|
147
|
+
let str;
|
|
148
|
+
if (typeof message === 'string')
|
|
149
|
+
str = message;
|
|
150
|
+
else if (message instanceof Uint8Array)
|
|
151
|
+
str = Buffer.from(message.buffer).toString();
|
|
152
|
+
else
|
|
153
|
+
return undefined;
|
|
154
|
+
return JSON.parse(str);
|
|
155
|
+
}
|
|
156
|
+
catch {
|
|
157
|
+
return undefined;
|
|
158
|
+
}
|
|
159
|
+
}
|
|
160
|
+
getMessageQueue() {
|
|
161
|
+
return getBindings().mq;
|
|
162
|
+
}
|
|
163
|
+
getUserSettings() {
|
|
164
|
+
return useUserSettings();
|
|
165
|
+
}
|
|
166
|
+
};
|
|
167
|
+
return FeatureToggleSyncService = _classThis;
|
|
168
|
+
})();
|
|
169
|
+
export { FeatureToggleSyncService };
|
|
170
|
+
export const useFeatureToggleSync = () => new FeatureToggleSyncService();
|
|
@@ -5,7 +5,7 @@ import { buildFileUrl, buildVideoUrl } from "../../base/parsers/utils";
|
|
|
5
5
|
import { getRouteHash } from "../../base/utils/route";
|
|
6
6
|
const MALFORMED_VIDEO_URL = /^video:\/{4,}/;
|
|
7
7
|
export const correctVideoUrl = (url, isMobile = false) => {
|
|
8
|
-
if (!url
|
|
8
|
+
if (!url?.startsWith('video:'))
|
|
9
9
|
return undefined;
|
|
10
10
|
const malformed = MALFORMED_VIDEO_URL.test(url);
|
|
11
11
|
if (!malformed && !isMobile)
|
|
@@ -882,13 +882,14 @@ let RouteListService = (() => {
|
|
|
882
882
|
if (!route.description.country) {
|
|
883
883
|
route.updateCountryFromPoints()
|
|
884
884
|
.then(() => {
|
|
885
|
-
this.logEvent({ message: 'preload route updated
|
|
885
|
+
this.logEvent({ message: 'preload route updated', route: card?.getData()?.title, reason: 'country added' });
|
|
886
886
|
this.db.save(route, false);
|
|
887
887
|
});
|
|
888
888
|
}
|
|
889
889
|
if (route.description.hasVideo && route.description.isDownloaded) {
|
|
890
890
|
card.videoExists().then(exists => {
|
|
891
891
|
if (!exists) {
|
|
892
|
+
this.logEvent({ message: 'preload route updated', route: card?.getData()?.title, reason: 'downloaded file missing' });
|
|
892
893
|
card.resetDownload();
|
|
893
894
|
}
|
|
894
895
|
});
|
package/lib/esm/ui/service.js
CHANGED
|
@@ -44,7 +44,7 @@ import { useFreeRideService, useRouteList } from "../routes";
|
|
|
44
44
|
import { useWorkoutList } from "../workouts";
|
|
45
45
|
import { useActiveRides, useActivityList } from "../activities";
|
|
46
46
|
import { useOnlineStatusMonitoring } from "../monitoring";
|
|
47
|
-
import { useAppState } from "../appstate";
|
|
47
|
+
import { useAppState, useFeatureToggleSync } from "../appstate";
|
|
48
48
|
import { IncyclistPageService } from "../base/pages";
|
|
49
49
|
import { waitNextTick } from "../utils";
|
|
50
50
|
const BACKGROUND_PAUSE_TIMEOUT_MS = 300000;
|
|
@@ -60,6 +60,7 @@ let UserInterfaceServcie = (() => {
|
|
|
60
60
|
let _getUserSettings_decorators;
|
|
61
61
|
let _getOnlineStatusMonitoring_decorators;
|
|
62
62
|
let _getAppState_decorators;
|
|
63
|
+
let _getFeatureToggleSync_decorators;
|
|
63
64
|
var UserInterfaceServcie = class extends _classSuper {
|
|
64
65
|
static { _classThis = this; }
|
|
65
66
|
static {
|
|
@@ -69,11 +70,13 @@ let UserInterfaceServcie = (() => {
|
|
|
69
70
|
_getUserSettings_decorators = [Injectable];
|
|
70
71
|
_getOnlineStatusMonitoring_decorators = [Injectable];
|
|
71
72
|
_getAppState_decorators = [Injectable];
|
|
73
|
+
_getFeatureToggleSync_decorators = [Injectable];
|
|
72
74
|
__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);
|
|
73
75
|
__esDecorate(this, null, _getMessageQueue_decorators, { kind: "method", name: "getMessageQueue", static: false, private: false, access: { has: obj => "getMessageQueue" in obj, get: obj => obj.getMessageQueue }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
74
76
|
__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);
|
|
75
77
|
__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);
|
|
76
78
|
__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);
|
|
79
|
+
__esDecorate(this, null, _getFeatureToggleSync_decorators, { kind: "method", name: "getFeatureToggleSync", static: false, private: false, access: { has: obj => "getFeatureToggleSync" in obj, get: obj => obj.getFeatureToggleSync }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
77
80
|
__esDecorate(null, _classDescriptor = { value: _classThis }, _classDecorators, { kind: "class", name: _classThis.name, metadata: _metadata }, null, _classExtraInitializers);
|
|
78
81
|
UserInterfaceServcie = _classThis = _classDescriptor.value;
|
|
79
82
|
if (_metadata) Object.defineProperty(_classThis, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
@@ -205,6 +208,7 @@ let UserInterfaceServcie = (() => {
|
|
|
205
208
|
const sent = false;
|
|
206
209
|
const user = this.getUserSettings().getValue('user', {});
|
|
207
210
|
const id = this.getUserSettings().getValue('uuid', undefined);
|
|
211
|
+
this.getFeatureToggleSync().start(id);
|
|
208
212
|
const { username, weight, ftp, gender } = user;
|
|
209
213
|
const topic = `incyclist/session/${this.session}/start`;
|
|
210
214
|
const os = this.getBindings().appInfo?.getOS()?.platform;
|
|
@@ -497,6 +501,9 @@ let UserInterfaceServcie = (() => {
|
|
|
497
501
|
getAppState() {
|
|
498
502
|
return useAppState();
|
|
499
503
|
}
|
|
504
|
+
getFeatureToggleSync() {
|
|
505
|
+
return useFeatureToggleSync();
|
|
506
|
+
}
|
|
500
507
|
};
|
|
501
508
|
return UserInterfaceServcie = _classThis;
|
|
502
509
|
})();
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import { IMessageQueueBinding } from "../api/mq";
|
|
2
|
+
import { IncyclistService } from "../base/service";
|
|
3
|
+
import { UserSettingsService } from "../settings/service/service";
|
|
4
|
+
import { FeatureToggle } from "./types";
|
|
5
|
+
export declare class FeatureToggleSyncService extends IncyclistService {
|
|
6
|
+
protected uuid: string;
|
|
7
|
+
protected subscribed: boolean;
|
|
8
|
+
protected onMessageHandler: any;
|
|
9
|
+
constructor();
|
|
10
|
+
start(uuid: string): void;
|
|
11
|
+
stop(): void;
|
|
12
|
+
protected getTopic(uuid: string): string;
|
|
13
|
+
protected getTopicPrefix(): string | undefined;
|
|
14
|
+
protected onMessage(topic: string, message: string | Uint8Array): void;
|
|
15
|
+
protected parseToggleName(topic: string, prefix: string): FeatureToggle | undefined;
|
|
16
|
+
protected parsePayload(message: string | Uint8Array): {
|
|
17
|
+
value?: boolean;
|
|
18
|
+
} | undefined;
|
|
19
|
+
protected getMessageQueue(): IMessageQueueBinding;
|
|
20
|
+
protected getUserSettings(): UserSettingsService;
|
|
21
|
+
}
|
|
22
|
+
export declare const useFeatureToggleSync: () => FeatureToggleSyncService;
|
|
@@ -56,5 +56,6 @@ export declare class UserInterfaceServcie extends IncyclistService {
|
|
|
56
56
|
protected getUserSettings(): import("../settings").UserSettingsService;
|
|
57
57
|
protected getOnlineStatusMonitoring(): OnlineStateMonitoringService;
|
|
58
58
|
protected getAppState(): import("../appstate").AppStateService;
|
|
59
|
+
protected getFeatureToggleSync(): import("../appstate").FeatureToggleSyncService;
|
|
59
60
|
}
|
|
60
61
|
export declare const useIncyclist: () => UserInterfaceServcie;
|