@netless/slide 1.4.60-alpha.0 → 1.4.61-beta.0
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/README.md +5 -10
- package/lib/AliTrackLogger.js +516 -0
- package/lib/FrozenTaskManager.d.ts +6 -3
- package/lib/FrozenTaskManager.js +73 -0
- package/lib/Lock.js +54 -0
- package/lib/PlayerContextReleaseWait.js +41 -0
- package/lib/PlayerController.js +175 -0
- package/lib/RenderSlideVisibility.js +16 -0
- package/lib/RenderingTaskManager.js +230 -0
- package/lib/Slide.d.ts +4 -3
- package/lib/Slide.js +1 -1
- package/lib/SyncTaskManager.js +206 -0
- package/lib/global.js +118 -0
- package/package.json +2 -2
package/README.md
CHANGED
|
@@ -4,17 +4,12 @@
|
|
|
4
4
|
|
|
5
5
|
## changelog
|
|
6
6
|
|
|
7
|
-
### 1.4.60
|
|
8
|
-
*
|
|
9
|
-
*
|
|
7
|
+
### 1.4.60 (2026-09-21)
|
|
8
|
+
* 新增 PPT 媒体权限回调和点击恢复接口:`onPptMediaPermissionRequest(callback)`、`playPptMedia()`
|
|
9
|
+
* 修复部分移动浏览器中 PPT 音视频无法自动播放或恢复的问题
|
|
10
10
|
|
|
11
|
-
### 1.4.59
|
|
12
|
-
*
|
|
13
|
-
* 修正 Howler `playerror` 在内部状态已变为 playing 但 DOM 仍 paused 时被误过滤的问题
|
|
14
|
-
|
|
15
|
-
### 1.4.59-alpha.0 (2026-09-11)
|
|
16
|
-
* 新增 `onPptMediaPermissionRequest(callback)` 接口,用于通知当前 PPT 音视频需要用户交互后才能播放
|
|
17
|
-
* 新增 `playPptMedia()` 接口,用于在用户点击事件中恢复当前仍处于播放状态、且本地被浏览器拦截的 PPT 音视频
|
|
11
|
+
### 1.4.59 (2026-09-18)
|
|
12
|
+
* 优化移动端切页时的播放器和 WebGL 资源管理,减少白屏和资源残留
|
|
18
13
|
|
|
19
14
|
### 1.4.58 (2026-09-07)
|
|
20
15
|
* 修复低版本 WebView 中纯色图形显示为黑块的问题
|
|
@@ -0,0 +1,516 @@
|
|
|
1
|
+
var __assign = (this && this.__assign) || function () {
|
|
2
|
+
__assign = Object.assign || function(t) {
|
|
3
|
+
for (var s, i = 1, n = arguments.length; i < n; i++) {
|
|
4
|
+
s = arguments[i];
|
|
5
|
+
for (var p in s) if (Object.prototype.hasOwnProperty.call(s, p))
|
|
6
|
+
t[p] = s[p];
|
|
7
|
+
}
|
|
8
|
+
return t;
|
|
9
|
+
};
|
|
10
|
+
return __assign.apply(this, arguments);
|
|
11
|
+
};
|
|
12
|
+
var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) {
|
|
13
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
14
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
15
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
16
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
17
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
18
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
19
|
+
});
|
|
20
|
+
};
|
|
21
|
+
var __generator = (this && this.__generator) || function (thisArg, body) {
|
|
22
|
+
var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g;
|
|
23
|
+
return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g;
|
|
24
|
+
function verb(n) { return function (v) { return step([n, v]); }; }
|
|
25
|
+
function step(op) {
|
|
26
|
+
if (f) throw new TypeError("Generator is already executing.");
|
|
27
|
+
while (_) try {
|
|
28
|
+
if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t;
|
|
29
|
+
if (y = 0, t) op = [op[0] & 2, t.value];
|
|
30
|
+
switch (op[0]) {
|
|
31
|
+
case 0: case 1: t = op; break;
|
|
32
|
+
case 4: _.label++; return { value: op[1], done: false };
|
|
33
|
+
case 5: _.label++; y = op[1]; op = [0]; continue;
|
|
34
|
+
case 7: op = _.ops.pop(); _.trys.pop(); continue;
|
|
35
|
+
default:
|
|
36
|
+
if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; }
|
|
37
|
+
if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; }
|
|
38
|
+
if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; }
|
|
39
|
+
if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; }
|
|
40
|
+
if (t[2]) _.ops.pop();
|
|
41
|
+
_.trys.pop(); continue;
|
|
42
|
+
}
|
|
43
|
+
op = body.call(thisArg, _);
|
|
44
|
+
} catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; }
|
|
45
|
+
if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true };
|
|
46
|
+
}
|
|
47
|
+
};
|
|
48
|
+
var AliTrackLogger = /** @class */ (function () {
|
|
49
|
+
function AliTrackLogger() {
|
|
50
|
+
var _this = this;
|
|
51
|
+
this.logList = [];
|
|
52
|
+
this.checkTimer = null;
|
|
53
|
+
this.retryTimes = 0;
|
|
54
|
+
this.enable = false;
|
|
55
|
+
this.db = null;
|
|
56
|
+
this.useIndexedDB = false;
|
|
57
|
+
this.DB_NAME = "__slide_logs_report__";
|
|
58
|
+
this.STORE_NAME = "logs";
|
|
59
|
+
this.BATCH_SIZE = 1000;
|
|
60
|
+
this.uploadLoggerGlobalEvent = function (event) {
|
|
61
|
+
if (event.data.type === "@slide/_upload_log_") {
|
|
62
|
+
_this.start();
|
|
63
|
+
}
|
|
64
|
+
};
|
|
65
|
+
this.config = {
|
|
66
|
+
checkTime: 5000,
|
|
67
|
+
buffer: 300,
|
|
68
|
+
};
|
|
69
|
+
window.addEventListener("message", this.uploadLoggerGlobalEvent);
|
|
70
|
+
this.initIndexedDB();
|
|
71
|
+
}
|
|
72
|
+
AliTrackLogger.prototype.initIndexedDB = function () {
|
|
73
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
74
|
+
var request_1;
|
|
75
|
+
var _this = this;
|
|
76
|
+
return __generator(this, function (_a) {
|
|
77
|
+
if (!('indexedDB' in window)) {
|
|
78
|
+
this.useIndexedDB = false;
|
|
79
|
+
this.start();
|
|
80
|
+
return [2 /*return*/];
|
|
81
|
+
}
|
|
82
|
+
try {
|
|
83
|
+
request_1 = indexedDB.open(this.DB_NAME, 1);
|
|
84
|
+
request_1.onerror = function () {
|
|
85
|
+
_this.useIndexedDB = false;
|
|
86
|
+
};
|
|
87
|
+
request_1.onsuccess = function () {
|
|
88
|
+
_this.start();
|
|
89
|
+
_this.db = request_1.result;
|
|
90
|
+
_this.useIndexedDB = true;
|
|
91
|
+
};
|
|
92
|
+
request_1.onupgradeneeded = function (event) {
|
|
93
|
+
var db = event.target.result;
|
|
94
|
+
if (!db.objectStoreNames.contains(_this.STORE_NAME)) {
|
|
95
|
+
var store = db.createObjectStore(_this.STORE_NAME, { keyPath: 'id', autoIncrement: true });
|
|
96
|
+
store.createIndex('timestamp', 'timestamp');
|
|
97
|
+
}
|
|
98
|
+
};
|
|
99
|
+
}
|
|
100
|
+
catch (error) {
|
|
101
|
+
this.useIndexedDB = false;
|
|
102
|
+
}
|
|
103
|
+
return [2 /*return*/];
|
|
104
|
+
});
|
|
105
|
+
});
|
|
106
|
+
};
|
|
107
|
+
AliTrackLogger.prototype.storeLogInIndexedDB = function (log) {
|
|
108
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
109
|
+
var error_1;
|
|
110
|
+
var _this = this;
|
|
111
|
+
return __generator(this, function (_a) {
|
|
112
|
+
switch (_a.label) {
|
|
113
|
+
case 0:
|
|
114
|
+
if (!this.useIndexedDB)
|
|
115
|
+
return [2 /*return*/];
|
|
116
|
+
_a.label = 1;
|
|
117
|
+
case 1:
|
|
118
|
+
_a.trys.push([1, 4, , 5]);
|
|
119
|
+
if (!(!this.db || !this.isDatabaseHealthy())) return [3 /*break*/, 3];
|
|
120
|
+
return [4 /*yield*/, this.recreateDatabase()];
|
|
121
|
+
case 2:
|
|
122
|
+
_a.sent();
|
|
123
|
+
if (!this.db || !this.useIndexedDB) {
|
|
124
|
+
throw new Error('Database not available after recreation attempt');
|
|
125
|
+
}
|
|
126
|
+
_a.label = 3;
|
|
127
|
+
case 3: return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
128
|
+
var transaction = _this.db.transaction([_this.STORE_NAME], 'readwrite');
|
|
129
|
+
var store = transaction.objectStore(_this.STORE_NAME);
|
|
130
|
+
var request = store.add(log);
|
|
131
|
+
transaction.onerror = function () {
|
|
132
|
+
// If transaction fails due to database being deleted, try to recreate
|
|
133
|
+
_this.recreateDatabase().then(function () {
|
|
134
|
+
if (!_this.db || !_this.useIndexedDB) {
|
|
135
|
+
reject(new Error('Database recreation failed'));
|
|
136
|
+
}
|
|
137
|
+
else {
|
|
138
|
+
// Retry the operation after recreation
|
|
139
|
+
var retryTransaction = _this.db.transaction([_this.STORE_NAME], 'readwrite');
|
|
140
|
+
var retryStore = retryTransaction.objectStore(_this.STORE_NAME);
|
|
141
|
+
var retryRequest_1 = retryStore.add(log);
|
|
142
|
+
retryRequest_1.onsuccess = function () { return resolve(); };
|
|
143
|
+
retryRequest_1.onerror = function () { return reject(retryRequest_1.error); };
|
|
144
|
+
}
|
|
145
|
+
}).catch(function (error) {
|
|
146
|
+
console.warn('Database recreation failed:', error);
|
|
147
|
+
// Fall back to memory storage and reject
|
|
148
|
+
_this.useIndexedDB = false;
|
|
149
|
+
reject(error);
|
|
150
|
+
});
|
|
151
|
+
};
|
|
152
|
+
request.onsuccess = function () { return resolve(); };
|
|
153
|
+
request.onerror = function () {
|
|
154
|
+
var _a, _b;
|
|
155
|
+
if (((_a = request.error) === null || _a === void 0 ? void 0 : _a.name) === 'UnknownError' || ((_b = request.error) === null || _b === void 0 ? void 0 : _b.name) === 'NotFoundError') {
|
|
156
|
+
// Database might have been deleted, try to recreate
|
|
157
|
+
_this.recreateDatabase().catch(function (error) {
|
|
158
|
+
console.warn('Database recreation failed:', error);
|
|
159
|
+
_this.useIndexedDB = false;
|
|
160
|
+
}).finally(function () { return reject(request.error); });
|
|
161
|
+
}
|
|
162
|
+
else {
|
|
163
|
+
reject(request.error);
|
|
164
|
+
}
|
|
165
|
+
};
|
|
166
|
+
})];
|
|
167
|
+
case 4:
|
|
168
|
+
error_1 = _a.sent();
|
|
169
|
+
this.useIndexedDB = false;
|
|
170
|
+
throw error_1;
|
|
171
|
+
case 5: return [2 /*return*/];
|
|
172
|
+
}
|
|
173
|
+
});
|
|
174
|
+
});
|
|
175
|
+
};
|
|
176
|
+
AliTrackLogger.prototype.getLogsFromIndexedDB = function (limit) {
|
|
177
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
178
|
+
var error_2;
|
|
179
|
+
var _this = this;
|
|
180
|
+
return __generator(this, function (_a) {
|
|
181
|
+
switch (_a.label) {
|
|
182
|
+
case 0:
|
|
183
|
+
if (!this.useIndexedDB)
|
|
184
|
+
return [2 /*return*/, []];
|
|
185
|
+
_a.label = 1;
|
|
186
|
+
case 1:
|
|
187
|
+
_a.trys.push([1, 4, , 5]);
|
|
188
|
+
if (!(!this.db || !this.isDatabaseHealthy())) return [3 /*break*/, 3];
|
|
189
|
+
return [4 /*yield*/, this.recreateDatabase()];
|
|
190
|
+
case 2:
|
|
191
|
+
_a.sent();
|
|
192
|
+
if (!this.db || !this.useIndexedDB) {
|
|
193
|
+
return [2 /*return*/, []];
|
|
194
|
+
}
|
|
195
|
+
_a.label = 3;
|
|
196
|
+
case 3: return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
197
|
+
var transaction = _this.db.transaction([_this.STORE_NAME], 'readonly');
|
|
198
|
+
var store = transaction.objectStore(_this.STORE_NAME);
|
|
199
|
+
var index = store.index('timestamp');
|
|
200
|
+
var request = index.openCursor(null, 'next');
|
|
201
|
+
var logs = [];
|
|
202
|
+
transaction.onerror = function () {
|
|
203
|
+
var _a, _b;
|
|
204
|
+
if (((_a = transaction.error) === null || _a === void 0 ? void 0 : _a.name) === 'UnknownError' || ((_b = transaction.error) === null || _b === void 0 ? void 0 : _b.name) === 'NotFoundError') {
|
|
205
|
+
_this.recreateDatabase().catch(function (error) {
|
|
206
|
+
console.warn('Database recreation failed:', error);
|
|
207
|
+
_this.useIndexedDB = false;
|
|
208
|
+
}).finally(function () { return resolve([]); });
|
|
209
|
+
}
|
|
210
|
+
else {
|
|
211
|
+
reject(transaction.error);
|
|
212
|
+
}
|
|
213
|
+
};
|
|
214
|
+
request.onsuccess = function (event) {
|
|
215
|
+
var cursor = event.target.result;
|
|
216
|
+
if (cursor && logs.length < limit) {
|
|
217
|
+
logs.push(cursor.value);
|
|
218
|
+
cursor.continue();
|
|
219
|
+
}
|
|
220
|
+
else {
|
|
221
|
+
resolve(logs.map(function (item) {
|
|
222
|
+
var _a;
|
|
223
|
+
return __assign(__assign({}, item), { id: (_a = item.id) === null || _a === void 0 ? void 0 : _a.toString() });
|
|
224
|
+
}));
|
|
225
|
+
}
|
|
226
|
+
};
|
|
227
|
+
request.onerror = function () {
|
|
228
|
+
var _a, _b;
|
|
229
|
+
if (((_a = request.error) === null || _a === void 0 ? void 0 : _a.name) === 'UnknownError' || ((_b = request.error) === null || _b === void 0 ? void 0 : _b.name) === 'NotFoundError') {
|
|
230
|
+
_this.recreateDatabase().catch(function (error) {
|
|
231
|
+
console.warn('Database recreation failed:', error);
|
|
232
|
+
_this.useIndexedDB = false;
|
|
233
|
+
}).finally(function () { return resolve([]); });
|
|
234
|
+
}
|
|
235
|
+
else {
|
|
236
|
+
reject(request.error);
|
|
237
|
+
}
|
|
238
|
+
};
|
|
239
|
+
})];
|
|
240
|
+
case 4:
|
|
241
|
+
error_2 = _a.sent();
|
|
242
|
+
this.useIndexedDB = false;
|
|
243
|
+
return [2 /*return*/, []];
|
|
244
|
+
case 5: return [2 /*return*/];
|
|
245
|
+
}
|
|
246
|
+
});
|
|
247
|
+
});
|
|
248
|
+
};
|
|
249
|
+
AliTrackLogger.prototype.deleteLogsFromIndexedDB = function (logsToDelete) {
|
|
250
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
251
|
+
var error_3;
|
|
252
|
+
var _this = this;
|
|
253
|
+
return __generator(this, function (_a) {
|
|
254
|
+
switch (_a.label) {
|
|
255
|
+
case 0:
|
|
256
|
+
if (!this.useIndexedDB || logsToDelete.length === 0)
|
|
257
|
+
return [2 /*return*/];
|
|
258
|
+
_a.label = 1;
|
|
259
|
+
case 1:
|
|
260
|
+
_a.trys.push([1, 4, , 5]);
|
|
261
|
+
if (!(!this.db || !this.isDatabaseHealthy())) return [3 /*break*/, 3];
|
|
262
|
+
return [4 /*yield*/, this.recreateDatabase()];
|
|
263
|
+
case 2:
|
|
264
|
+
_a.sent();
|
|
265
|
+
if (!this.db || !this.useIndexedDB) {
|
|
266
|
+
return [2 /*return*/];
|
|
267
|
+
}
|
|
268
|
+
_a.label = 3;
|
|
269
|
+
case 3: return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
270
|
+
var transaction = _this.db.transaction([_this.STORE_NAME], 'readwrite');
|
|
271
|
+
var store = transaction.objectStore(_this.STORE_NAME);
|
|
272
|
+
var deletePromises = logsToDelete.map(function (log) {
|
|
273
|
+
return new Promise(function (resolveDelete, rejectDelete) {
|
|
274
|
+
var logId = Number(log.id);
|
|
275
|
+
if (logId) {
|
|
276
|
+
var request_2 = store.delete(logId);
|
|
277
|
+
request_2.onsuccess = function () { return resolveDelete(); };
|
|
278
|
+
request_2.onerror = function () {
|
|
279
|
+
var _a, _b;
|
|
280
|
+
if (((_a = request_2.error) === null || _a === void 0 ? void 0 : _a.name) === 'UnknownError' || ((_b = request_2.error) === null || _b === void 0 ? void 0 : _b.name) === 'NotFoundError') {
|
|
281
|
+
// Database might have been deleted, ignore deletion errors
|
|
282
|
+
resolveDelete();
|
|
283
|
+
}
|
|
284
|
+
else {
|
|
285
|
+
rejectDelete(request_2.error);
|
|
286
|
+
}
|
|
287
|
+
};
|
|
288
|
+
}
|
|
289
|
+
else {
|
|
290
|
+
resolveDelete();
|
|
291
|
+
}
|
|
292
|
+
});
|
|
293
|
+
});
|
|
294
|
+
transaction.onerror = function () {
|
|
295
|
+
var _a, _b;
|
|
296
|
+
if (((_a = transaction.error) === null || _a === void 0 ? void 0 : _a.name) === 'UnknownError' || ((_b = transaction.error) === null || _b === void 0 ? void 0 : _b.name) === 'NotFoundError') {
|
|
297
|
+
_this.recreateDatabase().catch(function (error) {
|
|
298
|
+
console.warn('Database recreation failed:', error);
|
|
299
|
+
_this.useIndexedDB = false;
|
|
300
|
+
}).finally(function () { return resolve(); });
|
|
301
|
+
}
|
|
302
|
+
else {
|
|
303
|
+
reject(transaction.error);
|
|
304
|
+
}
|
|
305
|
+
};
|
|
306
|
+
Promise.all(deletePromises)
|
|
307
|
+
.then(function () { return resolve(); })
|
|
308
|
+
.catch(reject);
|
|
309
|
+
})];
|
|
310
|
+
case 4:
|
|
311
|
+
error_3 = _a.sent();
|
|
312
|
+
this.useIndexedDB = false;
|
|
313
|
+
return [3 /*break*/, 5];
|
|
314
|
+
case 5: return [2 /*return*/];
|
|
315
|
+
}
|
|
316
|
+
});
|
|
317
|
+
});
|
|
318
|
+
};
|
|
319
|
+
AliTrackLogger.prototype.start = function () {
|
|
320
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
321
|
+
var _this = this;
|
|
322
|
+
return __generator(this, function (_a) {
|
|
323
|
+
clearInterval(this.checkTimer);
|
|
324
|
+
this.checkTimer = setInterval(function () { return __awaiter(_this, void 0, void 0, function () {
|
|
325
|
+
return __generator(this, function (_a) {
|
|
326
|
+
switch (_a.label) {
|
|
327
|
+
case 0: return [4 /*yield*/, this.uploadLog()];
|
|
328
|
+
case 1:
|
|
329
|
+
_a.sent();
|
|
330
|
+
return [2 /*return*/];
|
|
331
|
+
}
|
|
332
|
+
});
|
|
333
|
+
}); }, this.config.checkTime);
|
|
334
|
+
return [2 /*return*/];
|
|
335
|
+
});
|
|
336
|
+
});
|
|
337
|
+
};
|
|
338
|
+
AliTrackLogger.prototype.pause = function () {
|
|
339
|
+
clearInterval(this.checkTimer);
|
|
340
|
+
};
|
|
341
|
+
AliTrackLogger.prototype.addLog = function (message, level, taskId, randomId) {
|
|
342
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
343
|
+
var log, error_4;
|
|
344
|
+
return __generator(this, function (_a) {
|
|
345
|
+
switch (_a.label) {
|
|
346
|
+
case 0:
|
|
347
|
+
log = { level: level, taskId: taskId, message: message, randomId: randomId, timestamp: Date.now().toString() };
|
|
348
|
+
if (!this.useIndexedDB) return [3 /*break*/, 5];
|
|
349
|
+
_a.label = 1;
|
|
350
|
+
case 1:
|
|
351
|
+
_a.trys.push([1, 3, , 4]);
|
|
352
|
+
return [4 /*yield*/, this.storeLogInIndexedDB(log)];
|
|
353
|
+
case 2:
|
|
354
|
+
_a.sent();
|
|
355
|
+
return [3 /*break*/, 4];
|
|
356
|
+
case 3:
|
|
357
|
+
error_4 = _a.sent();
|
|
358
|
+
this.logList.push(log);
|
|
359
|
+
return [3 /*break*/, 4];
|
|
360
|
+
case 4: return [3 /*break*/, 6];
|
|
361
|
+
case 5:
|
|
362
|
+
this.logList.push(log);
|
|
363
|
+
_a.label = 6;
|
|
364
|
+
case 6: return [2 /*return*/];
|
|
365
|
+
}
|
|
366
|
+
});
|
|
367
|
+
});
|
|
368
|
+
};
|
|
369
|
+
AliTrackLogger.prototype.isDatabaseHealthy = function () {
|
|
370
|
+
if (!this.db)
|
|
371
|
+
return false;
|
|
372
|
+
try {
|
|
373
|
+
// Check if the database connection is still valid and object store exists
|
|
374
|
+
var transaction = this.db.transaction([this.STORE_NAME], 'readonly');
|
|
375
|
+
var store = transaction.objectStore(this.STORE_NAME);
|
|
376
|
+
// Actually try to access the store to validate it exists and works
|
|
377
|
+
var index = store.index('timestamp');
|
|
378
|
+
return true;
|
|
379
|
+
}
|
|
380
|
+
catch (error) {
|
|
381
|
+
console.warn('Database health check failed:', error);
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
};
|
|
385
|
+
AliTrackLogger.prototype.recreateDatabase = function () {
|
|
386
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
387
|
+
var _this = this;
|
|
388
|
+
return __generator(this, function (_a) {
|
|
389
|
+
return [2 /*return*/, new Promise(function (resolve, reject) {
|
|
390
|
+
try {
|
|
391
|
+
// Close existing connection if any
|
|
392
|
+
if (_this.db) {
|
|
393
|
+
_this.db.close();
|
|
394
|
+
_this.db = null;
|
|
395
|
+
}
|
|
396
|
+
var request_3 = indexedDB.open(_this.DB_NAME, 1);
|
|
397
|
+
request_3.onerror = function () {
|
|
398
|
+
_this.useIndexedDB = false;
|
|
399
|
+
reject(request_3.error);
|
|
400
|
+
};
|
|
401
|
+
request_3.onsuccess = function () {
|
|
402
|
+
_this.db = request_3.result;
|
|
403
|
+
_this.useIndexedDB = true;
|
|
404
|
+
resolve();
|
|
405
|
+
};
|
|
406
|
+
request_3.onupgradeneeded = function (event) {
|
|
407
|
+
var db = event.target.result;
|
|
408
|
+
if (!db.objectStoreNames.contains(_this.STORE_NAME)) {
|
|
409
|
+
var store = db.createObjectStore(_this.STORE_NAME, { keyPath: 'id', autoIncrement: true });
|
|
410
|
+
store.createIndex('timestamp', 'timestamp');
|
|
411
|
+
}
|
|
412
|
+
};
|
|
413
|
+
}
|
|
414
|
+
catch (error) {
|
|
415
|
+
_this.useIndexedDB = false;
|
|
416
|
+
reject(error);
|
|
417
|
+
}
|
|
418
|
+
})];
|
|
419
|
+
});
|
|
420
|
+
});
|
|
421
|
+
};
|
|
422
|
+
AliTrackLogger.prototype.destroy = function () {
|
|
423
|
+
clearInterval(this.checkTimer);
|
|
424
|
+
window.removeEventListener("message", this.uploadLoggerGlobalEvent);
|
|
425
|
+
if (this.db) {
|
|
426
|
+
this.db.close();
|
|
427
|
+
this.db = null;
|
|
428
|
+
}
|
|
429
|
+
};
|
|
430
|
+
AliTrackLogger.prototype.uploadLog = function (focus) {
|
|
431
|
+
if (focus === void 0) { focus = false; }
|
|
432
|
+
return __awaiter(this, void 0, void 0, function () {
|
|
433
|
+
var uploadLog, errHandle, res, e_1;
|
|
434
|
+
var _this = this;
|
|
435
|
+
return __generator(this, function (_a) {
|
|
436
|
+
switch (_a.label) {
|
|
437
|
+
case 0:
|
|
438
|
+
uploadLog = [];
|
|
439
|
+
if (!this.useIndexedDB) return [3 /*break*/, 2];
|
|
440
|
+
return [4 /*yield*/, this.getLogsFromIndexedDB(this.BATCH_SIZE)];
|
|
441
|
+
case 1:
|
|
442
|
+
uploadLog = _a.sent();
|
|
443
|
+
if (uploadLog.length === 0) {
|
|
444
|
+
return [2 /*return*/];
|
|
445
|
+
}
|
|
446
|
+
return [3 /*break*/, 3];
|
|
447
|
+
case 2:
|
|
448
|
+
if (!(this.logList.length >= this.config.buffer || focus)) {
|
|
449
|
+
return [2 /*return*/];
|
|
450
|
+
}
|
|
451
|
+
uploadLog = this.logList.splice(0);
|
|
452
|
+
_a.label = 3;
|
|
453
|
+
case 3:
|
|
454
|
+
errHandle = function () {
|
|
455
|
+
if (!_this.useIndexedDB) {
|
|
456
|
+
_this.logList = uploadLog.concat(_this.logList);
|
|
457
|
+
}
|
|
458
|
+
if (_this.retryTimes > 3) {
|
|
459
|
+
_this.pause();
|
|
460
|
+
}
|
|
461
|
+
_this.retryTimes += 1;
|
|
462
|
+
};
|
|
463
|
+
_a.label = 4;
|
|
464
|
+
case 4:
|
|
465
|
+
_a.trys.push([4, 10, , 11]);
|
|
466
|
+
return [4 /*yield*/, fetch("https://netless-ppt-plugin-dev.cn-hangzhou.log.aliyuncs.com/logstores/netless-ppt-plugin-dev/track", {
|
|
467
|
+
method: "POST",
|
|
468
|
+
headers: {
|
|
469
|
+
"x-log-apiversion": "0.6.0",
|
|
470
|
+
"Content-Type": "application/json",
|
|
471
|
+
"Accept": "*/*"
|
|
472
|
+
},
|
|
473
|
+
body: JSON.stringify({
|
|
474
|
+
__topic__: "netless-ppt-plugin-dev",
|
|
475
|
+
__source__: "netless-ppt-plugin-dev",
|
|
476
|
+
__logs__: uploadLog,
|
|
477
|
+
})
|
|
478
|
+
})];
|
|
479
|
+
case 5:
|
|
480
|
+
res = _a.sent();
|
|
481
|
+
if (!res.ok) return [3 /*break*/, 8];
|
|
482
|
+
this.retryTimes = 0;
|
|
483
|
+
if (!this.useIndexedDB) return [3 /*break*/, 7];
|
|
484
|
+
return [4 /*yield*/, this.deleteLogsFromIndexedDB(uploadLog)];
|
|
485
|
+
case 6:
|
|
486
|
+
_a.sent();
|
|
487
|
+
_a.label = 7;
|
|
488
|
+
case 7: return [3 /*break*/, 9];
|
|
489
|
+
case 8:
|
|
490
|
+
errHandle();
|
|
491
|
+
_a.label = 9;
|
|
492
|
+
case 9: return [3 /*break*/, 11];
|
|
493
|
+
case 10:
|
|
494
|
+
e_1 = _a.sent();
|
|
495
|
+
console.warn(e_1);
|
|
496
|
+
errHandle();
|
|
497
|
+
return [3 /*break*/, 11];
|
|
498
|
+
case 11: return [2 /*return*/];
|
|
499
|
+
}
|
|
500
|
+
});
|
|
501
|
+
});
|
|
502
|
+
};
|
|
503
|
+
AliTrackLogger.prototype.setEnable = function (enable) {
|
|
504
|
+
if (this.enable === enable) {
|
|
505
|
+
return;
|
|
506
|
+
}
|
|
507
|
+
if (enable) {
|
|
508
|
+
this.start();
|
|
509
|
+
}
|
|
510
|
+
else {
|
|
511
|
+
this.pause();
|
|
512
|
+
}
|
|
513
|
+
};
|
|
514
|
+
return AliTrackLogger;
|
|
515
|
+
}());
|
|
516
|
+
export { AliTrackLogger };
|
|
@@ -2,13 +2,16 @@ export interface FrozenTask {
|
|
|
2
2
|
type: "frozen" | "release";
|
|
3
3
|
status: "running" | "wait";
|
|
4
4
|
fn: () => Promise<void>;
|
|
5
|
+
promise: Promise<void>;
|
|
6
|
+
resolve: () => void;
|
|
7
|
+
reject: (error: unknown) => void;
|
|
5
8
|
}
|
|
6
9
|
export declare class FrozenTaskManager {
|
|
7
10
|
private tasks;
|
|
8
11
|
private isDestroy;
|
|
9
|
-
private
|
|
12
|
+
private runningTask?;
|
|
10
13
|
private schedule;
|
|
11
14
|
private getRunningTask;
|
|
12
|
-
addTask(type: "frozen" | "release", fn: () => Promise<void>): void
|
|
13
|
-
destroy(): void
|
|
15
|
+
addTask(type: "frozen" | "release", fn: () => Promise<void>): Promise<void>;
|
|
16
|
+
destroy(): Promise<void>;
|
|
14
17
|
}
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
var FrozenTaskManager = /** @class */ (function () {
|
|
2
|
+
function FrozenTaskManager() {
|
|
3
|
+
var _this = this;
|
|
4
|
+
this.tasks = [];
|
|
5
|
+
this.isDestroy = false;
|
|
6
|
+
this.schedule = function () {
|
|
7
|
+
if (_this.runningTask || _this.isDestroy) {
|
|
8
|
+
return;
|
|
9
|
+
}
|
|
10
|
+
var task = _this.tasks.shift();
|
|
11
|
+
if (!task) {
|
|
12
|
+
return;
|
|
13
|
+
}
|
|
14
|
+
task.status = "running";
|
|
15
|
+
_this.runningTask = task;
|
|
16
|
+
void task.fn.apply(null).then(task.resolve, task.reject).finally(function () {
|
|
17
|
+
if (_this.runningTask === task) {
|
|
18
|
+
_this.runningTask = undefined;
|
|
19
|
+
}
|
|
20
|
+
if (!_this.isDestroy && _this.tasks.length > 0) {
|
|
21
|
+
setTimeout(_this.schedule);
|
|
22
|
+
}
|
|
23
|
+
});
|
|
24
|
+
};
|
|
25
|
+
}
|
|
26
|
+
FrozenTaskManager.prototype.getRunningTask = function () {
|
|
27
|
+
var _a;
|
|
28
|
+
return (_a = this.runningTask) !== null && _a !== void 0 ? _a : null;
|
|
29
|
+
};
|
|
30
|
+
FrozenTaskManager.prototype.addTask = function (type, fn) {
|
|
31
|
+
if (this.isDestroy) {
|
|
32
|
+
return Promise.resolve();
|
|
33
|
+
}
|
|
34
|
+
var runningTask = this.getRunningTask();
|
|
35
|
+
if (runningTask && type === runningTask.type) {
|
|
36
|
+
return runningTask.promise;
|
|
37
|
+
}
|
|
38
|
+
var queuedTask = this.tasks.find(function (task) { return task.type === type; });
|
|
39
|
+
if (queuedTask) {
|
|
40
|
+
return queuedTask.promise;
|
|
41
|
+
}
|
|
42
|
+
var resolveTask;
|
|
43
|
+
var rejectTask;
|
|
44
|
+
var promise = new Promise(function (resolve, reject) {
|
|
45
|
+
resolveTask = resolve;
|
|
46
|
+
rejectTask = reject;
|
|
47
|
+
});
|
|
48
|
+
// Existing callers are allowed to ignore frozen()/release(). Keep the
|
|
49
|
+
// original promise observable to awaiters without creating an
|
|
50
|
+
// unhandled rejection for legacy fire-and-forget calls.
|
|
51
|
+
promise.catch(function () { return undefined; });
|
|
52
|
+
var task = {
|
|
53
|
+
type: type,
|
|
54
|
+
status: "wait",
|
|
55
|
+
fn: fn,
|
|
56
|
+
promise: promise,
|
|
57
|
+
resolve: resolveTask,
|
|
58
|
+
reject: rejectTask,
|
|
59
|
+
};
|
|
60
|
+
this.tasks.push(task);
|
|
61
|
+
this.schedule();
|
|
62
|
+
return promise;
|
|
63
|
+
};
|
|
64
|
+
FrozenTaskManager.prototype.destroy = function () {
|
|
65
|
+
var _a, _b;
|
|
66
|
+
this.isDestroy = true;
|
|
67
|
+
var pending = this.tasks.splice(0, this.tasks.length);
|
|
68
|
+
pending.forEach(function (task) { return task.resolve(); });
|
|
69
|
+
return (_b = (_a = this.runningTask) === null || _a === void 0 ? void 0 : _a.promise.catch(function () { return undefined; })) !== null && _b !== void 0 ? _b : Promise.resolve();
|
|
70
|
+
};
|
|
71
|
+
return FrozenTaskManager;
|
|
72
|
+
}());
|
|
73
|
+
export { FrozenTaskManager };
|