@robotical/webapp-types 3.26.0 → 3.26.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.
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "marty-web-app",
3
- "version": "3.26.0",
3
+ "version": "3.26.2",
4
4
  "private": true,
5
5
  "engines": {
6
6
  "node": ">=20"
@@ -65,6 +65,10 @@ export type AppUpdateSnapshot = {
65
65
  capability: typeof UPDATE_UI_CAPABILITY;
66
66
  nativeUpdate: NativeAppUpdate | null;
67
67
  webUpdate: WebAppUpdate | null;
68
+ webDownload?: {
69
+ webappVersion: string;
70
+ progress?: number;
71
+ } | null;
68
72
  checks?: {
69
73
  native: "checking" | "current" | "unknown";
70
74
  web: "checking" | "current" | "unknown";
@@ -54,6 +54,68 @@ export var UPDATE_REQUEST_TIMEOUT_MS = 20000;
54
54
  export var UPDATE_CHECK_STALE_MS = 30000;
55
55
  var readyRequest = null;
56
56
  var checkRequest = null;
57
+ var requestDeadlines = new Set();
58
+ // Called on native state messages too: WKWebView does not always emit browser
59
+ // lifecycle events when its containing native application becomes active.
60
+ var refreshRequestDeadlines = function () { return requestDeadlines.forEach(function (expire) { return expire(); }); };
61
+ var boundedRequest = function (operation, onExpire) {
62
+ var deadline = Date.now() + UPDATE_REQUEST_TIMEOUT_MS;
63
+ var active = true;
64
+ var timer;
65
+ var expire;
66
+ var timeout = new Promise(function (resolve) { expire = function () { return resolve(null); }; });
67
+ var expireIfOverdue = function () {
68
+ if (!active || Date.now() < deadline) {
69
+ return false;
70
+ }
71
+ active = false;
72
+ expire();
73
+ onExpire === null || onExpire === void 0 ? void 0 : onExpire();
74
+ return true;
75
+ };
76
+ var checkDeadline = function () {
77
+ clearTimeout(timer);
78
+ if (!expireIfOverdue() && active) {
79
+ timer = setTimeout(checkDeadline, Math.max(0, deadline - Date.now()));
80
+ }
81
+ };
82
+ var onVisible = function () { if (!document.hidden) {
83
+ checkDeadline();
84
+ } };
85
+ requestDeadlines.add(expireIfOverdue);
86
+ document.addEventListener('visibilitychange', onVisible);
87
+ window.addEventListener('pageshow', checkDeadline);
88
+ window.addEventListener('focus', checkDeadline);
89
+ checkDeadline();
90
+ var isActive = function () { return active && Date.now() < deadline; };
91
+ var promise = (function () { return __awaiter(void 0, void 0, void 0, function () {
92
+ var result, _a;
93
+ return __generator(this, function (_b) {
94
+ switch (_b.label) {
95
+ case 0:
96
+ _b.trys.push([0, 2, 3, 4]);
97
+ return [4 /*yield*/, Promise.race([operation(isActive), timeout])];
98
+ case 1:
99
+ result = _b.sent();
100
+ // Queued replies can run before pageshow/visibilitychange on resume.
101
+ return [2 /*return*/, isActive() ? result : null];
102
+ case 2:
103
+ _a = _b.sent();
104
+ return [2 /*return*/, null];
105
+ case 3:
106
+ active = false;
107
+ clearTimeout(timer);
108
+ requestDeadlines.delete(expireIfOverdue);
109
+ document.removeEventListener('visibilitychange', onVisible);
110
+ window.removeEventListener('pageshow', checkDeadline);
111
+ window.removeEventListener('focus', checkDeadline);
112
+ return [7 /*endfinally*/];
113
+ case 4: return [2 /*return*/];
114
+ }
115
+ });
116
+ }); })();
117
+ return { promise: promise, expireIfOverdue: expireIfOverdue };
118
+ };
57
119
  var isNativeUpdate = function (value) {
58
120
  if (!value || typeof value !== "object") {
59
121
  return false;
@@ -83,12 +145,16 @@ export var isAppUpdateSnapshot = function (value) {
83
145
  }));
84
146
  return (candidate.capability === UPDATE_UI_CAPABILITY &&
85
147
  (candidate.nativeUpdate === null || isNativeUpdate(candidate.nativeUpdate)) &&
86
- (candidate.webUpdate === null || isWebUpdate(candidate.webUpdate)) && validChecks);
148
+ (candidate.webUpdate === null || isWebUpdate(candidate.webUpdate)) && validChecks &&
149
+ (candidate.webDownload == null || (isWebUpdate(candidate.webDownload) &&
150
+ (candidate.webDownload.progress === undefined || (typeof candidate.webDownload.progress === 'number' &&
151
+ Number.isFinite(candidate.webDownload.progress) && candidate.webDownload.progress >= 0 && candidate.webDownload.progress <= 100)))));
87
152
  };
88
153
  export var publishPhoneAppUpdateState = function (value) {
89
154
  if (!isAppUpdateSnapshot(value)) {
90
155
  return;
91
156
  }
157
+ refreshRequestDeadlines();
92
158
  latestSnapshot = value;
93
159
  listeners.forEach(function (listener) { return listener(value); });
94
160
  };
@@ -137,8 +203,8 @@ export var usePhoneAppUpdates = function () {
137
203
  useCheckingDeadline('web', (_b = snapshot === null || snapshot === void 0 ? void 0 : snapshot.checks) === null || _b === void 0 ? void 0 : _b.web);
138
204
  return snapshot;
139
205
  };
140
- var requestUpdateState = function (message) { return __awaiter(void 0, void 0, void 0, function () {
141
- var timer, snapshot, _a;
206
+ var requestUpdateState = function (message, isActive) { return __awaiter(void 0, void 0, void 0, function () {
207
+ var snapshot, _a;
142
208
  return __generator(this, function (_b) {
143
209
  switch (_b.label) {
144
210
  case 0:
@@ -147,14 +213,11 @@ var requestUpdateState = function (message) { return __awaiter(void 0, void 0, v
147
213
  }
148
214
  _b.label = 1;
149
215
  case 1:
150
- _b.trys.push([1, 3, 4, 5]);
151
- return [4 /*yield*/, Promise.race([
152
- window.wrapperCommunicator.sendMessageAndWait(message, {}),
153
- new Promise(function (resolve) { timer = setTimeout(function () { return resolve(null); }, UPDATE_REQUEST_TIMEOUT_MS); }),
154
- ])];
216
+ _b.trys.push([1, 3, , 4]);
217
+ return [4 /*yield*/, window.wrapperCommunicator.sendMessageAndWait(message, {})];
155
218
  case 2:
156
219
  snapshot = _b.sent();
157
- if (!isAppUpdateSnapshot(snapshot)) {
220
+ if (!isActive() || !isAppUpdateSnapshot(snapshot)) {
158
221
  return [2 /*return*/, null];
159
222
  }
160
223
  publishPhoneAppUpdateState(snapshot);
@@ -162,61 +225,73 @@ var requestUpdateState = function (message) { return __awaiter(void 0, void 0, v
162
225
  case 3:
163
226
  _a = _b.sent();
164
227
  return [2 /*return*/, null];
165
- case 4:
166
- clearTimeout(timer);
167
- return [7 /*endfinally*/];
168
- case 5: return [2 /*return*/];
228
+ case 4: return [2 /*return*/];
169
229
  }
170
230
  });
171
231
  }); };
172
232
  export var announcePhoneAppUpdateUiReady = function () {
173
- if (!readyRequest) {
174
- readyRequest = requestUpdateState(AppSentMessage.UPDATE_UI_READY).finally(function () { readyRequest = null; });
233
+ if (!readyRequest || readyRequest.expireIfOverdue()) {
234
+ var request_1 = boundedRequest(function (active) { return requestUpdateState(AppSentMessage.UPDATE_UI_READY, active); });
235
+ readyRequest = request_1;
236
+ void request_1.promise.finally(function () { if (readyRequest === request_1) {
237
+ readyRequest = null;
238
+ } });
175
239
  }
176
- return readyRequest;
240
+ return readyRequest.promise;
177
241
  };
178
242
  export var getPhoneAppUpdateState = function () {
179
- return requestUpdateState(AppSentMessage.UPDATE_GET_STATE);
243
+ return boundedRequest(function (active) { return requestUpdateState(AppSentMessage.UPDATE_GET_STATE, active); }).promise;
180
244
  };
181
- var performUpdateCheck = function () { return __awaiter(void 0, void 0, void 0, function () {
182
- var _a, supportsChecks, result, _b, native, web;
183
- return __generator(this, function (_c) {
184
- switch (_c.label) {
245
+ var performUpdateCheck = function (isActive) { return __awaiter(void 0, void 0, void 0, function () {
246
+ var _a, supportsChecks;
247
+ return __generator(this, function (_b) {
248
+ switch (_b.label) {
185
249
  case 0:
186
250
  _a = !latestSnapshot;
187
251
  if (!_a) return [3 /*break*/, 2];
188
252
  return [4 /*yield*/, announcePhoneAppUpdateUiReady()];
189
253
  case 1:
190
- _a = !(_c.sent());
191
- _c.label = 2;
254
+ _a = !(_b.sent());
255
+ _b.label = 2;
192
256
  case 2:
193
257
  // A lost cold-start reply must not permanently remove access to update checks.
194
258
  if (_a) {
195
259
  return [2 /*return*/, null];
196
260
  }
261
+ if (!isActive()) {
262
+ return [2 /*return*/, null];
263
+ }
197
264
  supportsChecks = Boolean(latestSnapshot === null || latestSnapshot === void 0 ? void 0 : latestSnapshot.checks);
198
265
  if (latestSnapshot && supportsChecks) {
199
266
  publishPhoneAppUpdateState(__assign(__assign({}, latestSnapshot), { checks: { native: "checking", web: "checking" } }));
200
267
  }
201
- return [4 /*yield*/, requestUpdateState(supportsChecks ? AppSentMessage.UPDATE_CHECK_NOW : AppSentMessage.UPDATE_GET_STATE)];
202
- case 3:
203
- result = _c.sent();
204
- if (!result && (latestSnapshot === null || latestSnapshot === void 0 ? void 0 : latestSnapshot.checks)) {
205
- _b = latestSnapshot.checks, native = _b.native, web = _b.web;
206
- publishPhoneAppUpdateState(__assign(__assign({}, latestSnapshot), { checks: {
207
- native: native === "checking" ? "unknown" : native,
208
- web: web === "checking" ? "unknown" : web,
209
- } }));
210
- }
211
- return [2 /*return*/, result];
268
+ return [2 /*return*/, requestUpdateState(supportsChecks ? AppSentMessage.UPDATE_CHECK_NOW : AppSentMessage.UPDATE_GET_STATE, isActive)];
212
269
  }
213
270
  });
214
271
  }); };
272
+ var expireCheckingState = function () {
273
+ if (latestSnapshot === null || latestSnapshot === void 0 ? void 0 : latestSnapshot.checks) {
274
+ var _a = latestSnapshot.checks, native = _a.native, web = _a.web;
275
+ publishPhoneAppUpdateState(__assign(__assign({}, latestSnapshot), { checks: {
276
+ native: native === "checking" ? "unknown" : native,
277
+ web: web === "checking" ? "unknown" : web,
278
+ } }));
279
+ }
280
+ };
215
281
  export var checkPhoneAppUpdates = function () {
216
- if (!checkRequest) {
217
- checkRequest = performUpdateCheck().finally(function () { checkRequest = null; });
282
+ if (!checkRequest || checkRequest.expireIfOverdue()) {
283
+ var request_2 = boundedRequest(performUpdateCheck, expireCheckingState);
284
+ checkRequest = request_2;
285
+ void request_2.promise.then(function (result) {
286
+ if (checkRequest === request_2) {
287
+ if (!result) {
288
+ expireCheckingState();
289
+ }
290
+ checkRequest = null;
291
+ }
292
+ });
218
293
  }
219
- return checkRequest;
294
+ return checkRequest.promise;
220
295
  };
221
296
  export var applyPhoneWebUpdate = function () { return __awaiter(void 0, void 0, void 0, function () {
222
297
  var response, _a;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@robotical/webapp-types",
3
- "version": "3.26.0",
3
+ "version": "3.26.2",
4
4
  "description": "Type definitions for the Application Manager",
5
5
  "main": "dist/application-manager.d.ts",
6
6
  "types": "dist/application-manager.d.ts",