@plasosdk/plaso-electron-sdk 1.3.17-beta.2 → 1.3.17
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/.prettierrc +8 -8
- package/CHANGELOG.md +13 -13
- package/README.md +805 -802
- package/index.html +275 -275
- package/index.js +6 -6
- package/js/macro.js +103 -103
- package/js/main.js +34 -34
- package/js/render.d.ts +100 -98
- package/js/render.js +509 -523
- package/js/util.js +109 -109
- package/jsconfig.json +10 -10
- package/package.json +29 -29
- package/scripts/getConfig.js +16 -16
- package/scripts/install.js +165 -165
- package/scripts/logger.js +138 -138
package/js/render.js
CHANGED
|
@@ -1,523 +1,509 @@
|
|
|
1
|
-
const path = require('path');
|
|
2
|
-
const { ERROR_CODE, LESSON_TYPE, CLASS_WINDOW_MESG_TYPE, RENDER_TO_MAIN_MESG_TYPE, FILE_TYPE } = require('./macro');
|
|
3
|
-
const getConfig = require('../scripts/getConfig');
|
|
4
|
-
const LogFormatter = require('../scripts/logger');
|
|
5
|
-
const { getElectronRemote, parseUrlParams, getDisplayMatching } = require('./util');
|
|
6
|
-
|
|
7
|
-
const remote = getElectronRemote();
|
|
8
|
-
const isMac = getConfig().platform === 'darwin';
|
|
9
|
-
|
|
10
|
-
// logger
|
|
11
|
-
const defaultLoggerPath = remote ? path.join(remote.app.getPath('userData'), '/P403FileTemp/') : '';
|
|
12
|
-
const logger = new LogFormatter(defaultLoggerPath);
|
|
13
|
-
logger.init();
|
|
14
|
-
|
|
15
|
-
let currentWinId = null;
|
|
16
|
-
let currentWebContentsId = null;
|
|
17
|
-
|
|
18
|
-
/**
|
|
19
|
-
* @param {import('./render').ClassWindowType} classWindowProps
|
|
20
|
-
* @returns {number}
|
|
21
|
-
*/
|
|
22
|
-
function createClassWindow(classWindowProps) {
|
|
23
|
-
const {
|
|
24
|
-
classOptions,
|
|
25
|
-
electronWinOptions,
|
|
26
|
-
onClassWindowReadyFn,
|
|
27
|
-
onClassWindowLeaveFn,
|
|
28
|
-
onClassFinishedFn,
|
|
29
|
-
onSaveBoardFn,
|
|
30
|
-
onOpenResourceCenterFn,
|
|
31
|
-
onGetExtFileNameFn,
|
|
32
|
-
onGetPreParseFileNameFn,
|
|
33
|
-
onReportIssuesFn,
|
|
34
|
-
} = classWindowProps;
|
|
35
|
-
|
|
36
|
-
const onFetchFavoritesFn = classWindowProps.browserOptions?.onFetchFavoritesFn;
|
|
37
|
-
const onFetchCategoriesFn = classWindowProps.browserOptions?.onFetchCategoriesFn;
|
|
38
|
-
const onAddFavoriteFn = classWindowProps.browserOptions?.onAddFavoriteFn;
|
|
39
|
-
const onRemoveFavoriteFn = classWindowProps.browserOptions?.onRemoveFavoriteFn;
|
|
40
|
-
|
|
41
|
-
logger.info('课堂窗口创建信息', {
|
|
42
|
-
version: getVersion(),
|
|
43
|
-
classOptions: classOptions,
|
|
44
|
-
electronWinOptions: electronWinOptions,
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
/* ----------------------------------- 守卫 ----------------------------------- */
|
|
48
|
-
if (currentWinId) {
|
|
49
|
-
logger.warn('课堂窗口同时仅能存在一个');
|
|
50
|
-
return ERROR_CODE.CLASS_WINODW_GREATER_THAN_ONE;
|
|
51
|
-
}
|
|
52
|
-
|
|
53
|
-
const isElectron = !!process?.versions?.['electron'];
|
|
54
|
-
if (!isElectron) {
|
|
55
|
-
logger.error('非 Electron 环境');
|
|
56
|
-
return ERROR_CODE.NO_ELECTRON_ENVIRONMENT;
|
|
57
|
-
}
|
|
58
|
-
|
|
59
|
-
if (!remote) {
|
|
60
|
-
logger.error('获取 remote 失败');
|
|
61
|
-
return ERROR_CODE.GET_REMOTE_FAIL;
|
|
62
|
-
}
|
|
63
|
-
|
|
64
|
-
const displayInfo = getDisplayMatching();
|
|
65
|
-
if (!displayInfo) {
|
|
66
|
-
logger.error('获取 displayInfo 失败');
|
|
67
|
-
return ERROR_CODE.GET_DISPLAY_INFO_FAIL;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
/* ---------------------------- 拼凑 globalAppInfo ---------------------------- */
|
|
71
|
-
const openerId = remote.getCurrentWebContents().id;
|
|
72
|
-
const queryObj = classOptions.query ? parseUrlParams(classOptions.query) : {};
|
|
73
|
-
const autoMaximized = true;
|
|
74
|
-
const env = classOptions.env ? classOptions.env.toLowerCase() : 'www';
|
|
75
|
-
|
|
76
|
-
const getHost = () => {
|
|
77
|
-
let rhost
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
*
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
});
|
|
316
|
-
|
|
317
|
-
const
|
|
318
|
-
requestMsgType: CLASS_WINDOW_MESG_TYPE.
|
|
319
|
-
|
|
320
|
-
callback:
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
requestMsgType:
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
|
|
383
|
-
|
|
384
|
-
|
|
385
|
-
|
|
386
|
-
|
|
387
|
-
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
|
|
391
|
-
|
|
392
|
-
|
|
393
|
-
|
|
394
|
-
|
|
395
|
-
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
442
|
-
|
|
443
|
-
|
|
444
|
-
|
|
445
|
-
|
|
446
|
-
|
|
447
|
-
|
|
448
|
-
|
|
449
|
-
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
|
|
459
|
-
|
|
460
|
-
|
|
461
|
-
|
|
462
|
-
|
|
463
|
-
|
|
464
|
-
|
|
465
|
-
|
|
466
|
-
|
|
467
|
-
|
|
468
|
-
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
|
|
476
|
-
|
|
477
|
-
|
|
478
|
-
|
|
479
|
-
|
|
480
|
-
|
|
481
|
-
|
|
482
|
-
|
|
483
|
-
|
|
484
|
-
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
505
|
-
|
|
506
|
-
|
|
507
|
-
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
updateProhibitedWords(words) {
|
|
511
|
-
try {
|
|
512
|
-
if (currentWebContentsId) {
|
|
513
|
-
window
|
|
514
|
-
.require('electron')
|
|
515
|
-
.ipcRenderer //
|
|
516
|
-
.sendTo(currentWebContentsId, CLASS_WINDOW_MESG_TYPE.UPDATE_SENSITIVE_WORDS, words || []);
|
|
517
|
-
}
|
|
518
|
-
} catch (error) {
|
|
519
|
-
logger.error(`updateProhibitedWords error is: ${JSON.stringify(error)}}`);
|
|
520
|
-
return ERROR_CODE.COMMOM_ERROR;
|
|
521
|
-
}
|
|
522
|
-
},
|
|
523
|
-
};
|
|
1
|
+
const path = require('path');
|
|
2
|
+
const { ERROR_CODE, LESSON_TYPE, CLASS_WINDOW_MESG_TYPE, RENDER_TO_MAIN_MESG_TYPE, FILE_TYPE } = require('./macro');
|
|
3
|
+
const getConfig = require('../scripts/getConfig');
|
|
4
|
+
const LogFormatter = require('../scripts/logger');
|
|
5
|
+
const { getElectronRemote, parseUrlParams, getDisplayMatching } = require('./util');
|
|
6
|
+
|
|
7
|
+
const remote = getElectronRemote();
|
|
8
|
+
const isMac = getConfig().platform === 'darwin';
|
|
9
|
+
|
|
10
|
+
// logger
|
|
11
|
+
const defaultLoggerPath = remote ? path.join(remote.app.getPath('userData'), '/P403FileTemp/') : '';
|
|
12
|
+
const logger = new LogFormatter(defaultLoggerPath);
|
|
13
|
+
logger.init();
|
|
14
|
+
|
|
15
|
+
let currentWinId = null;
|
|
16
|
+
let currentWebContentsId = null;
|
|
17
|
+
|
|
18
|
+
/**
|
|
19
|
+
* @param {import('./render').ClassWindowType} classWindowProps
|
|
20
|
+
* @returns {number}
|
|
21
|
+
*/
|
|
22
|
+
function createClassWindow(classWindowProps) {
|
|
23
|
+
const {
|
|
24
|
+
classOptions,
|
|
25
|
+
electronWinOptions,
|
|
26
|
+
onClassWindowReadyFn,
|
|
27
|
+
onClassWindowLeaveFn,
|
|
28
|
+
onClassFinishedFn,
|
|
29
|
+
onSaveBoardFn,
|
|
30
|
+
onOpenResourceCenterFn,
|
|
31
|
+
onGetExtFileNameFn,
|
|
32
|
+
onGetPreParseFileNameFn,
|
|
33
|
+
onReportIssuesFn,
|
|
34
|
+
} = classWindowProps;
|
|
35
|
+
|
|
36
|
+
const onFetchFavoritesFn = classWindowProps.browserOptions?.onFetchFavoritesFn;
|
|
37
|
+
const onFetchCategoriesFn = classWindowProps.browserOptions?.onFetchCategoriesFn;
|
|
38
|
+
const onAddFavoriteFn = classWindowProps.browserOptions?.onAddFavoriteFn;
|
|
39
|
+
const onRemoveFavoriteFn = classWindowProps.browserOptions?.onRemoveFavoriteFn;
|
|
40
|
+
|
|
41
|
+
logger.info('课堂窗口创建信息', {
|
|
42
|
+
version: getVersion(),
|
|
43
|
+
classOptions: classOptions,
|
|
44
|
+
electronWinOptions: electronWinOptions,
|
|
45
|
+
});
|
|
46
|
+
|
|
47
|
+
/* ----------------------------------- 守卫 ----------------------------------- */
|
|
48
|
+
if (currentWinId) {
|
|
49
|
+
logger.warn('课堂窗口同时仅能存在一个');
|
|
50
|
+
return ERROR_CODE.CLASS_WINODW_GREATER_THAN_ONE;
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
const isElectron = !!process?.versions?.['electron'];
|
|
54
|
+
if (!isElectron) {
|
|
55
|
+
logger.error('非 Electron 环境');
|
|
56
|
+
return ERROR_CODE.NO_ELECTRON_ENVIRONMENT;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
if (!remote) {
|
|
60
|
+
logger.error('获取 remote 失败');
|
|
61
|
+
return ERROR_CODE.GET_REMOTE_FAIL;
|
|
62
|
+
}
|
|
63
|
+
|
|
64
|
+
const displayInfo = getDisplayMatching();
|
|
65
|
+
if (!displayInfo) {
|
|
66
|
+
logger.error('获取 displayInfo 失败');
|
|
67
|
+
return ERROR_CODE.GET_DISPLAY_INFO_FAIL;
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/* ---------------------------- 拼凑 globalAppInfo ---------------------------- */
|
|
71
|
+
const openerId = remote.getCurrentWebContents().id;
|
|
72
|
+
const queryObj = classOptions.query ? parseUrlParams(classOptions.query) : {};
|
|
73
|
+
const autoMaximized = true;
|
|
74
|
+
const env = classOptions.env ? classOptions.env.toLowerCase() : 'www';
|
|
75
|
+
|
|
76
|
+
const getHost = () => {
|
|
77
|
+
let rhost = `https://wwwr.plaso.cn/static/sdk/styleupime/${classOptions.version ?? '1.68.110'}/`;
|
|
78
|
+
let dhost = 'https://www.plaso.cn/';
|
|
79
|
+
if (classOptions.rhost) {
|
|
80
|
+
rhost = classOptions.rhost; // 调试用,不对外
|
|
81
|
+
}
|
|
82
|
+
if (classOptions.dhost) {
|
|
83
|
+
dhost = classOptions.dhost;
|
|
84
|
+
}
|
|
85
|
+
return { rhost, dhost };
|
|
86
|
+
};
|
|
87
|
+
|
|
88
|
+
const globalAppInfo = {
|
|
89
|
+
...classOptions,
|
|
90
|
+
...queryObj,
|
|
91
|
+
...getHost(),
|
|
92
|
+
query: classOptions.query,
|
|
93
|
+
appType: classOptions.appType,
|
|
94
|
+
markString: env,
|
|
95
|
+
env,
|
|
96
|
+
classType: classOptions.classType,
|
|
97
|
+
onClose: 'close', // 让课堂里退出时标识状态,详情见commFunction.js
|
|
98
|
+
electronSdkLoggerPath: logger.loggerPath ?? '',
|
|
99
|
+
electronSdkLoggerName: logger.logFileName ?? '',
|
|
100
|
+
flameshotPath: isMac
|
|
101
|
+
? path.join(__dirname, '../lib/flameshot.app/Contents/MacOS/flameshot')
|
|
102
|
+
: path.join(__dirname, '../lib/flameshot/flameshot.exe'),
|
|
103
|
+
PlasoALDPath: isMac //
|
|
104
|
+
? path.join(__dirname, '../lib/PlasoALD')
|
|
105
|
+
: '',
|
|
106
|
+
clientType: 'electron',
|
|
107
|
+
isElectronSdk: true,
|
|
108
|
+
openerId,
|
|
109
|
+
memoryConfigKey: classOptions.memoryConfigKey ?? queryObj.loginName ?? classOptions.loginName ?? '',
|
|
110
|
+
maximized: autoMaximized,
|
|
111
|
+
fullScreenable: queryObj.userType === 'listener', // 课堂最大化按钮是否是切换全屏模式
|
|
112
|
+
supportOnReportIssues: !!onReportIssuesFn,
|
|
113
|
+
supportOnFetchFavorites: !!onFetchFavoritesFn,
|
|
114
|
+
supportOnFetchCategories: !!onFetchCategoriesFn,
|
|
115
|
+
supportOnAddFavorite: !!onAddFavoriteFn,
|
|
116
|
+
supportOnRemoveFavorite: !!onRemoveFavoriteFn,
|
|
117
|
+
};
|
|
118
|
+
|
|
119
|
+
if (globalAppInfo.userType === 'monitor') {
|
|
120
|
+
globalAppInfo.monitor = true;
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
/* ------------------------------ electron 窗口配置 ----------------------------- */
|
|
124
|
+
const buildElectronWinOptions = () => {
|
|
125
|
+
const buildBounds = () => {
|
|
126
|
+
const bounds = remote.getCurrentWindow().getBounds();
|
|
127
|
+
const screenWidth = displayInfo.size.width;
|
|
128
|
+
const screenWorkAreaWidth = displayInfo.workAreaSize.width;
|
|
129
|
+
const screenHeight = displayInfo.size.height;
|
|
130
|
+
const screenWorkAreaHeight = displayInfo.workAreaSize.height;
|
|
131
|
+
|
|
132
|
+
const changeBoundsDate = (ischangeWidth, baseWidthOrHeight) => {
|
|
133
|
+
const newWidthOrHeight = baseWidthOrHeight - 10;
|
|
134
|
+
if (ischangeWidth) {
|
|
135
|
+
bounds.height = Math.round((bounds.height * newWidthOrHeight) / bounds.width);
|
|
136
|
+
bounds.width = newWidthOrHeight;
|
|
137
|
+
} else {
|
|
138
|
+
bounds.width = Math.round((bounds.width * newWidthOrHeight) / bounds.height);
|
|
139
|
+
bounds.height = newWidthOrHeight;
|
|
140
|
+
}
|
|
141
|
+
};
|
|
142
|
+
// 课堂窗口创建时的宽或高和 屏幕宽高或屏幕工作区宽高 一致时,此时透明窗口会失效,需要调整进课堂时的窗口宽高
|
|
143
|
+
if (bounds.width === screenWidth || bounds.width === screenWorkAreaWidth) {
|
|
144
|
+
changeBoundsDate(true, Math.min(screenWidth, screenWorkAreaWidth));
|
|
145
|
+
}
|
|
146
|
+
if (bounds.height === screenHeight || bounds.height === screenWorkAreaHeight) {
|
|
147
|
+
changeBoundsDate(false, Math.min(screenHeight, screenWorkAreaHeight));
|
|
148
|
+
}
|
|
149
|
+
return bounds;
|
|
150
|
+
};
|
|
151
|
+
|
|
152
|
+
const defaultElectronWinOptions = {
|
|
153
|
+
frame: false,
|
|
154
|
+
/**
|
|
155
|
+
* electron 12.0.18之后,resizable设为true才能全屏和最大化,
|
|
156
|
+
* 而课堂窗口不允许通过electron自身的缩放行为来改变大小,因此进入课堂后会将resizable设为false
|
|
157
|
+
*/
|
|
158
|
+
resizable: true,
|
|
159
|
+
/** 设置为true,mac上setFullScreen(true)才生效,setSimpleFullScreen(true)不依赖此参数 */
|
|
160
|
+
fullscreenable: true,
|
|
161
|
+
...buildBounds(),
|
|
162
|
+
webPreferences: {
|
|
163
|
+
nodeIntegration: true,
|
|
164
|
+
enableRemoteModule: true,
|
|
165
|
+
contextIsolation: false,
|
|
166
|
+
nodeIntegrationInWorker: true,
|
|
167
|
+
webviewTag: true,
|
|
168
|
+
},
|
|
169
|
+
};
|
|
170
|
+
|
|
171
|
+
if (isMac) {
|
|
172
|
+
// 在Mac下要显式设置fullscreen为false,防止客户端全屏时进入课堂,课堂窗口也默认全屏,
|
|
173
|
+
// 导致部分按钮失效,以及独立窗口打开异常
|
|
174
|
+
defaultElectronWinOptions.fullscreen = false;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
// 学生无需使用透明窗口(透明窗口问题多),减少影响
|
|
178
|
+
if (queryObj.userType !== 'listener') {
|
|
179
|
+
defaultElectronWinOptions.transparent = true;
|
|
180
|
+
defaultElectronWinOptions.backgroundColor = '#00ffffff';
|
|
181
|
+
}
|
|
182
|
+
|
|
183
|
+
if (queryObj.topic) {
|
|
184
|
+
defaultElectronWinOptions.title = queryObj.topic + '';
|
|
185
|
+
}
|
|
186
|
+
if (classOptions.topic && classOptions.classType === LESSON_TYPE.PREPARE_LESSONS) {
|
|
187
|
+
defaultElectronWinOptions.title = classOptions.topic + '';
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
return {
|
|
191
|
+
...defaultElectronWinOptions,
|
|
192
|
+
...(electronWinOptions || {}),
|
|
193
|
+
};
|
|
194
|
+
};
|
|
195
|
+
|
|
196
|
+
/* -------------------------------- 回调 bridge ------------------------------- */
|
|
197
|
+
const { ipcRenderer } = window.require('electron');
|
|
198
|
+
|
|
199
|
+
/**
|
|
200
|
+
* 适用范围
|
|
201
|
+
* 用于创建带回复的回调,要求
|
|
202
|
+
* ipc-request payload 格式为 (requestId, ...args)
|
|
203
|
+
* ipc-response payload 格式为 (requestId, returnValue)
|
|
204
|
+
*
|
|
205
|
+
* 整条链路
|
|
206
|
+
* [课堂窗口] --ipc-request--> [Handler] --> [classWindowProps.onXxxFn] --> [Handler] --ipc-response--> [课堂窗口]
|
|
207
|
+
* 本函数用来构建这个桥接用的 handler
|
|
208
|
+
*
|
|
209
|
+
* 内部流程
|
|
210
|
+
* - step 1 执行 beforeCallback,如果返回 false 则中止
|
|
211
|
+
* - step 2 如果 callback 不存在则中止
|
|
212
|
+
* - step 3 执行 callback
|
|
213
|
+
* - step 4 执行 afterCallback,如果返回 false 则中止
|
|
214
|
+
* - step 5 则把 callback 返回值发给课堂窗口
|
|
215
|
+
*/
|
|
216
|
+
/** @type {import('./render').BuildReplyingCallback} */
|
|
217
|
+
const buildReplyingCallback = ({ requestMsgType, responseMsgType, callback, beforeCallback, afterCallback }) => {
|
|
218
|
+
return {
|
|
219
|
+
requestMsgType,
|
|
220
|
+
responseMsgType,
|
|
221
|
+
handler: async (event, requestId, ...args) => {
|
|
222
|
+
const info = `${requestMsgType} ${responseMsgType} ${requestId}`;
|
|
223
|
+
try {
|
|
224
|
+
logger.info(`[callback bridge] start ${info}`);
|
|
225
|
+
if (!currentWebContentsId || !responseMsgType || !requestId) {
|
|
226
|
+
return;
|
|
227
|
+
}
|
|
228
|
+
if (beforeCallback?.(...args) === false) {
|
|
229
|
+
logger.info(`[callback bridge] beforeCallback guard, ${info}`);
|
|
230
|
+
return;
|
|
231
|
+
}
|
|
232
|
+
if (!callback) {
|
|
233
|
+
logger.info(`[callback bridge] callback is null, skip, ${info}`);
|
|
234
|
+
return;
|
|
235
|
+
}
|
|
236
|
+
const result = await callback(...args);
|
|
237
|
+
if (afterCallback?.(result) === false) {
|
|
238
|
+
logger.info(`[callback bridge] afterCallback guard, ${info}`);
|
|
239
|
+
return;
|
|
240
|
+
}
|
|
241
|
+
ipcRenderer.sendTo(currentWebContentsId, responseMsgType, requestId, result);
|
|
242
|
+
logger.info(`[callback bridge] end ${info}`);
|
|
243
|
+
} catch (error) {
|
|
244
|
+
logger.error(`[callback bridge] error ${info}`, error);
|
|
245
|
+
}
|
|
246
|
+
},
|
|
247
|
+
};
|
|
248
|
+
};
|
|
249
|
+
|
|
250
|
+
const onClassWindowReady = (event) => {
|
|
251
|
+
const classWindow = remote.BrowserWindow.fromId(currentWinId);
|
|
252
|
+
classWindow.moveTop();
|
|
253
|
+
classWindow.focus();
|
|
254
|
+
logger.info(`课堂窗口ready,id:${currentWinId}`);
|
|
255
|
+
if (onClassWindowReadyFn && currentWinId) {
|
|
256
|
+
onClassWindowReadyFn(currentWinId);
|
|
257
|
+
}
|
|
258
|
+
};
|
|
259
|
+
|
|
260
|
+
const onClassFinished = (event, value) => {
|
|
261
|
+
const meetingId = value?.meetingId;
|
|
262
|
+
logger.info(`课堂已结束,id:${currentWinId}, meetingId is ${meetingId}`);
|
|
263
|
+
if (onClassFinishedFn && currentWinId) {
|
|
264
|
+
onClassFinishedFn(meetingId);
|
|
265
|
+
}
|
|
266
|
+
};
|
|
267
|
+
|
|
268
|
+
const onHtmlReady = (event, value) => {
|
|
269
|
+
currentWebContentsId = value?.webContentId;
|
|
270
|
+
logger.info(`课堂窗口 html ready,web contents id:${currentWebContentsId}`);
|
|
271
|
+
if (currentWebContentsId) {
|
|
272
|
+
ipcRenderer.sendTo(currentWebContentsId, CLASS_WINDOW_MESG_TYPE.INIT_GLOBAL_APPINFO, globalAppInfo);
|
|
273
|
+
}
|
|
274
|
+
};
|
|
275
|
+
|
|
276
|
+
const onSaveBoard = (event, value) => {
|
|
277
|
+
logger.info(`保存板书:${JSON.stringify(value)}`);
|
|
278
|
+
if (onSaveBoardFn && value) {
|
|
279
|
+
onSaveBoardFn(value, (value) => {
|
|
280
|
+
if (currentWebContentsId) {
|
|
281
|
+
ipcRenderer.sendTo(currentWebContentsId, CLASS_WINDOW_MESG_TYPE.RESP_SAVE_BOARD, value);
|
|
282
|
+
}
|
|
283
|
+
});
|
|
284
|
+
}
|
|
285
|
+
};
|
|
286
|
+
|
|
287
|
+
const onOpenResourceCenter = (event) => {
|
|
288
|
+
onOpenResourceCenterFn?.();
|
|
289
|
+
};
|
|
290
|
+
|
|
291
|
+
const onReportIssues = (event, info) => {
|
|
292
|
+
onReportIssuesFn?.(info);
|
|
293
|
+
};
|
|
294
|
+
|
|
295
|
+
const onGetExtFileName = buildReplyingCallback({
|
|
296
|
+
requestMsgType: CLASS_WINDOW_MESG_TYPE.GET_EXT_FILE_NAME,
|
|
297
|
+
beforeCallback: (...args) => args.length > 0,
|
|
298
|
+
callback: onGetExtFileNameFn,
|
|
299
|
+
afterCallback: (result) => !!result,
|
|
300
|
+
responseMsgType: CLASS_WINDOW_MESG_TYPE.RESP_GET_EXT_FILE_NAME,
|
|
301
|
+
});
|
|
302
|
+
|
|
303
|
+
const onGetPreParseFileName = buildReplyingCallback({
|
|
304
|
+
requestMsgType: CLASS_WINDOW_MESG_TYPE.GET_PRE_PARSE_FILE_NAME,
|
|
305
|
+
beforeCallback: (...args) => args.length > 0,
|
|
306
|
+
callback: onGetPreParseFileNameFn,
|
|
307
|
+
afterCallback: (result) => !!result,
|
|
308
|
+
responseMsgType: CLASS_WINDOW_MESG_TYPE.RESP_GET_PRE_PARSE_FILE_NAME,
|
|
309
|
+
});
|
|
310
|
+
|
|
311
|
+
const onFetchFavorites = buildReplyingCallback({
|
|
312
|
+
requestMsgType: CLASS_WINDOW_MESG_TYPE.FETCH_FAVORITES,
|
|
313
|
+
responseMsgType: CLASS_WINDOW_MESG_TYPE.RESP_FETCH_FAVORITES,
|
|
314
|
+
callback: onFetchFavoritesFn,
|
|
315
|
+
});
|
|
316
|
+
|
|
317
|
+
const onFetchCategories = buildReplyingCallback({
|
|
318
|
+
requestMsgType: CLASS_WINDOW_MESG_TYPE.FETCH_CATEGORIES,
|
|
319
|
+
responseMsgType: CLASS_WINDOW_MESG_TYPE.RESP_FETCH_CATEGORIES,
|
|
320
|
+
callback: onFetchCategoriesFn,
|
|
321
|
+
});
|
|
322
|
+
|
|
323
|
+
const onAddFavorite = buildReplyingCallback({
|
|
324
|
+
requestMsgType: CLASS_WINDOW_MESG_TYPE.ADD_FAVORITE,
|
|
325
|
+
responseMsgType: CLASS_WINDOW_MESG_TYPE.RESP_ADD_FAVORITE,
|
|
326
|
+
callback: onAddFavoriteFn,
|
|
327
|
+
});
|
|
328
|
+
|
|
329
|
+
const onRemoveFavorite = buildReplyingCallback({
|
|
330
|
+
requestMsgType: CLASS_WINDOW_MESG_TYPE.REMOVE_FAVORITE,
|
|
331
|
+
responseMsgType: CLASS_WINDOW_MESG_TYPE.RESP_REMOVE_FAVORITE,
|
|
332
|
+
callback: onRemoveFavoriteFn,
|
|
333
|
+
});
|
|
334
|
+
|
|
335
|
+
const callbacks = {
|
|
336
|
+
[CLASS_WINDOW_MESG_TYPE.LIVE_WINDOW_READY]: onClassWindowReady,
|
|
337
|
+
[CLASS_WINDOW_MESG_TYPE.ON_CLASS_FINISHED]: onClassFinished,
|
|
338
|
+
[CLASS_WINDOW_MESG_TYPE.HTML_READY]: onHtmlReady,
|
|
339
|
+
[CLASS_WINDOW_MESG_TYPE.SAVE_BOARD]: onSaveBoard,
|
|
340
|
+
[CLASS_WINDOW_MESG_TYPE.OPEN_RESOURCE_CENTER]: onOpenResourceCenter,
|
|
341
|
+
[CLASS_WINDOW_MESG_TYPE.REPORT_ISSUES]: onReportIssues,
|
|
342
|
+
[onGetExtFileName.requestMsgType]: onGetExtFileName.handler,
|
|
343
|
+
[onGetPreParseFileName.requestMsgType]: onGetPreParseFileName.handler,
|
|
344
|
+
[onFetchFavorites.requestMsgType]: onFetchFavorites.handler,
|
|
345
|
+
[onFetchCategories.requestMsgType]: onFetchCategories.handler,
|
|
346
|
+
[onAddFavorite.requestMsgType]: onAddFavorite.handler,
|
|
347
|
+
[onRemoveFavorite.requestMsgType]: onRemoveFavorite.handler,
|
|
348
|
+
};
|
|
349
|
+
|
|
350
|
+
Object.entries(callbacks).forEach(([type, callback]) => {
|
|
351
|
+
ipcRenderer.on(type, callback);
|
|
352
|
+
});
|
|
353
|
+
|
|
354
|
+
/* ---------------------------------- 窗口创建 ---------------------------------- */
|
|
355
|
+
const appProxy = require('@plasosdk/winproxy');
|
|
356
|
+
|
|
357
|
+
const indexHtmlPath = isMac
|
|
358
|
+
? require('url').format({
|
|
359
|
+
pathname: path.join(__dirname, '../index.html'),
|
|
360
|
+
protocol: 'file:',
|
|
361
|
+
slashes: true,
|
|
362
|
+
})
|
|
363
|
+
: path.join(__dirname, '../index.html');
|
|
364
|
+
|
|
365
|
+
appProxy.createWindow(
|
|
366
|
+
{
|
|
367
|
+
path: indexHtmlPath + `?openerId=${openerId}`,
|
|
368
|
+
debug: classOptions?.debug ?? false,
|
|
369
|
+
maximize: autoMaximized,
|
|
370
|
+
windowOptions: buildElectronWinOptions(),
|
|
371
|
+
},
|
|
372
|
+
onWindowCreated,
|
|
373
|
+
);
|
|
374
|
+
|
|
375
|
+
async function onWindowCreated(id) {
|
|
376
|
+
currentWinId = id;
|
|
377
|
+
appProxy.addWinEventListener(id, 'closed', onWindowClosed);
|
|
378
|
+
}
|
|
379
|
+
|
|
380
|
+
/* ---------------------------------- 窗口关闭 ---------------------------------- */
|
|
381
|
+
function onWindowClosed() {
|
|
382
|
+
logger.info(`课堂窗口关闭,id:${currentWinId}`);
|
|
383
|
+
onClassWindowLeaveFn?.(currentWinId);
|
|
384
|
+
currentWinId = null;
|
|
385
|
+
currentWebContentsId = null;
|
|
386
|
+
Object.entries(callbacks).forEach(([type, callback]) => {
|
|
387
|
+
ipcRenderer.removeListener(type, callback);
|
|
388
|
+
});
|
|
389
|
+
}
|
|
390
|
+
|
|
391
|
+
return 0;
|
|
392
|
+
}
|
|
393
|
+
|
|
394
|
+
function getVersion() {
|
|
395
|
+
try {
|
|
396
|
+
const packageJson = require('../package.json');
|
|
397
|
+
return packageJson.version;
|
|
398
|
+
} catch (error) {
|
|
399
|
+
logger.error(`getVersion error is: ${JSON.stringify(error)}}`);
|
|
400
|
+
return ERROR_CODE.COMMOM_ERROR;
|
|
401
|
+
}
|
|
402
|
+
}
|
|
403
|
+
|
|
404
|
+
/** Plaso Electron SDK */
|
|
405
|
+
module.exports = {
|
|
406
|
+
/**
|
|
407
|
+
* 课堂
|
|
408
|
+
* @param {import('./render').ClassWindowType} liveClassWindowProps
|
|
409
|
+
* @returns {number}
|
|
410
|
+
*/
|
|
411
|
+
createLiveClassWindow(liveClassWindowProps) {
|
|
412
|
+
try {
|
|
413
|
+
return createClassWindow({
|
|
414
|
+
...liveClassWindowProps,
|
|
415
|
+
classOptions: {
|
|
416
|
+
...liveClassWindowProps.classOptions,
|
|
417
|
+
appType: 'liveclassSDK',
|
|
418
|
+
classType: LESSON_TYPE.LIVECLASS,
|
|
419
|
+
},
|
|
420
|
+
});
|
|
421
|
+
} catch (error) {
|
|
422
|
+
logger.error(`异常错误,${JSON.stringify(error)}`);
|
|
423
|
+
return ERROR_CODE.COMMOM_ERROR;
|
|
424
|
+
}
|
|
425
|
+
},
|
|
426
|
+
|
|
427
|
+
/**
|
|
428
|
+
* 备课
|
|
429
|
+
* @param {import('./render').ClassWindowType} prepareClassWindowProps
|
|
430
|
+
* @returns {number}
|
|
431
|
+
*/
|
|
432
|
+
createPrepareClassWindow(prepareClassWindowProps) {
|
|
433
|
+
try {
|
|
434
|
+
return createClassWindow({
|
|
435
|
+
...prepareClassWindowProps,
|
|
436
|
+
classOptions: {
|
|
437
|
+
...prepareClassWindowProps.classOptions,
|
|
438
|
+
appType: 'prepareLessonSdk',
|
|
439
|
+
meetingType: LESSON_TYPE.PREPARE_LESSONS,
|
|
440
|
+
classType: LESSON_TYPE.PREPARE_LESSONS,
|
|
441
|
+
userType: 'speaker',
|
|
442
|
+
topic: prepareClassWindowProps.classOptions.topic ?? '备课课堂',
|
|
443
|
+
},
|
|
444
|
+
});
|
|
445
|
+
} catch (error) {
|
|
446
|
+
logger.error(`异常错误,${JSON.stringify(error)}`);
|
|
447
|
+
return ERROR_CODE.COMMOM_ERROR;
|
|
448
|
+
}
|
|
449
|
+
},
|
|
450
|
+
|
|
451
|
+
/**
|
|
452
|
+
* 获取 sdk 版本
|
|
453
|
+
*/
|
|
454
|
+
getVersion,
|
|
455
|
+
|
|
456
|
+
/**
|
|
457
|
+
*初始化日志文件路径
|
|
458
|
+
* @param {string} logFilePath 日志文件路径
|
|
459
|
+
*/
|
|
460
|
+
initLogConfig(logFilePath) {
|
|
461
|
+
if (logFilePath) {
|
|
462
|
+
logger.initLoggerFilePath(logFilePath);
|
|
463
|
+
require('electron')
|
|
464
|
+
.ipcRenderer //
|
|
465
|
+
.send(RENDER_TO_MAIN_MESG_TYPE.PLASO_INIT_LOG_PATH, logFilePath);
|
|
466
|
+
}
|
|
467
|
+
},
|
|
468
|
+
|
|
469
|
+
/**
|
|
470
|
+
* 插入的资源文件类型定义
|
|
471
|
+
*/
|
|
472
|
+
FILE_TYPE,
|
|
473
|
+
|
|
474
|
+
/**
|
|
475
|
+
* 插入外部云盘里的文件,文件需要遵循特定的数据结构
|
|
476
|
+
* @param {import('./render').FileDataObj} fileData 文件数据
|
|
477
|
+
*/
|
|
478
|
+
insertObject(fileData) {
|
|
479
|
+
try {
|
|
480
|
+
if (currentWebContentsId) {
|
|
481
|
+
window
|
|
482
|
+
.require('electron')
|
|
483
|
+
.ipcRenderer //
|
|
484
|
+
.sendTo(currentWebContentsId, CLASS_WINDOW_MESG_TYPE.INSERT_OBJECT, fileData);
|
|
485
|
+
}
|
|
486
|
+
} catch (error) {
|
|
487
|
+
logger.error(`insertObject error is: ${JSON.stringify(error)}}`);
|
|
488
|
+
return ERROR_CODE.COMMOM_ERROR;
|
|
489
|
+
}
|
|
490
|
+
},
|
|
491
|
+
|
|
492
|
+
/**
|
|
493
|
+
* 更新严禁词列表
|
|
494
|
+
* @param {string[]} words 严禁词数组
|
|
495
|
+
*/
|
|
496
|
+
updateProhibitedWords(words) {
|
|
497
|
+
try {
|
|
498
|
+
if (currentWebContentsId) {
|
|
499
|
+
window
|
|
500
|
+
.require('electron')
|
|
501
|
+
.ipcRenderer //
|
|
502
|
+
.sendTo(currentWebContentsId, CLASS_WINDOW_MESG_TYPE.UPDATE_SENSITIVE_WORDS, words || []);
|
|
503
|
+
}
|
|
504
|
+
} catch (error) {
|
|
505
|
+
logger.error(`updateProhibitedWords error is: ${JSON.stringify(error)}}`);
|
|
506
|
+
return ERROR_CODE.COMMOM_ERROR;
|
|
507
|
+
}
|
|
508
|
+
},
|
|
509
|
+
};
|