@lynker-desktop/electron-window-manager 0.0.9-alpha.3 → 0.0.9-alpha.5

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/main/index.js CHANGED
@@ -70,12 +70,19 @@ class WindowsManager {
70
70
  * - 'localhost'、'127.0.0.1'、'::1' 以及局域网 IP(如 192.168.x.x、10.x.x.x、172.16.x.x~172.31.x.x)都视为本地白名单。
71
71
  */
72
72
  constructor(preload, loadingViewUrl, errorViewUrl, preloadWebContentsUrl, webviewDomainWhiteList) {
73
+ // 预加载的窗口
73
74
  this.preloadedBW = null;
75
+ // 预加载的窗口(无边框,有按钮)
74
76
  this.preloadedBW_FramelessWithButtons = null;
77
+ // 预加载的窗口(无边框,无按钮)
75
78
  this.preloadedBW_FramelessNoButtons = null;
79
+ // 预加载的浏览器视图
76
80
  this.preloadedBV = null;
77
81
  this.preloading = false;
78
82
  this.webviewDomainWhiteList = [];
83
+ // 创建队列相关属性
84
+ this.createQueue = [];
85
+ this.isCreating = false;
79
86
  this.preload = preload;
80
87
  this.windows = new Map();
81
88
  this.loadingViewUrl = `${loadingViewUrl ?? ''}`;
@@ -85,10 +92,16 @@ class WindowsManager {
85
92
  log('log', 'preloadWebContentsUrl: ', this.preloadWebContentsUrl);
86
93
  if (this.preloadWebContentsUrl) {
87
94
  electron.app.on('ready', () => {
88
- this._preloadInstances();
95
+ if (this.preloadWebContentsUrl) {
96
+ this.setPreloadWebContentsUrl(this.preloadWebContentsUrl);
97
+ }
89
98
  });
90
99
  }
91
100
  }
101
+ /**
102
+ * 设置预加载的webContents的url
103
+ * @param preloadWebContentsUrl 预加载的webContents的url
104
+ */
92
105
  setPreloadWebContentsUrl(preloadWebContentsUrl) {
93
106
  try {
94
107
  this.preloadWebContentsUrl = preloadWebContentsUrl;
@@ -106,23 +119,30 @@ class WindowsManager {
106
119
  log('error', 'setPreloadWebContentsUrl error:', error);
107
120
  }
108
121
  }
122
+ /**
123
+ * 预加载实例
124
+ */
109
125
  async _preloadInstances() {
110
126
  if (this.preloading)
111
127
  return;
112
128
  this.preloading = true;
113
129
  try {
114
130
  if (this.preloadWebContentsUrl) {
131
+ // 预加载的窗口
115
132
  this.preloadedBW = this.preloadedBW || await this._createPreloadBW({});
133
+ // 预加载的窗口(无边框,有按钮)
116
134
  this.preloadedBW_FramelessWithButtons = this.preloadedBW_FramelessWithButtons || await this._createPreloadBW({
117
135
  frame: false,
118
136
  transparent: true,
119
137
  titleBarStyle: 'hidden',
120
138
  });
139
+ // 预加载的窗口(无边框,无按钮)
121
140
  this.preloadedBW_FramelessNoButtons = this.preloadedBW_FramelessNoButtons || await this._createPreloadBW({
122
141
  frame: false,
123
142
  transparent: true,
124
143
  titleBarStyle: 'customButtonsOnHover',
125
144
  });
145
+ // 预加载的BV
126
146
  this.preloadedBV = this.preloadedBV || await this._createPreloadBV();
127
147
  }
128
148
  }
@@ -131,15 +151,21 @@ class WindowsManager {
131
151
  }
132
152
  this.preloading = false;
133
153
  }
154
+ /**
155
+ * 创建预加载的窗口
156
+ * @param options 窗口选项
157
+ * @returns 预加载的窗口
158
+ */
134
159
  _createPreloadBW(options = {}) {
135
160
  return new Promise((resolve) => {
136
161
  const preload = this.preload;
137
162
  const url = this.preloadWebContentsUrl;
138
163
  if (this.preloadWebContentsUrl) {
139
164
  const instance = new electron.BrowserWindow({
140
- show: false,
141
165
  ...options,
166
+ show: false,
142
167
  webPreferences: {
168
+ ...(options.webPreferences || {}),
143
169
  webviewTag: true,
144
170
  plugins: true,
145
171
  nodeIntegration: true,
@@ -147,7 +173,6 @@ class WindowsManager {
147
173
  backgroundThrottling: false,
148
174
  webSecurity: false,
149
175
  preload: preload,
150
- ...(options.webPreferences || {}),
151
176
  }
152
177
  });
153
178
  try {
@@ -171,10 +196,14 @@ class WindowsManager {
171
196
  instance.webContents.once('did-fail-load', () => {
172
197
  resolve(instance);
173
198
  });
174
- instance.loadURL(url || 'about:blank');
199
+ instance.loadURL(url ? `${url}` : 'about:blank');
175
200
  }
176
201
  });
177
202
  }
203
+ /**
204
+ * 创建预加载的浏览器视图
205
+ * @returns 预加载的浏览器视图
206
+ */
178
207
  _createPreloadBV() {
179
208
  return new Promise((resolve) => {
180
209
  const preload = this.preload;
@@ -217,6 +246,40 @@ class WindowsManager {
217
246
  });
218
247
  }
219
248
  create(options) {
249
+ return new Promise((resolve, reject) => {
250
+ // 将创建请求添加到队列
251
+ this.createQueue.push({ options, resolve, reject });
252
+ // 如果当前没有在创建,则开始处理队列
253
+ if (!this.isCreating) {
254
+ this.processCreateQueue();
255
+ }
256
+ });
257
+ }
258
+ /**
259
+ * 处理创建队列
260
+ */
261
+ async processCreateQueue() {
262
+ if (this.isCreating || this.createQueue.length === 0) {
263
+ return;
264
+ }
265
+ this.isCreating = true;
266
+ while (this.createQueue.length > 0) {
267
+ const { options, resolve, reject } = this.createQueue.shift();
268
+ try {
269
+ const window = await this._createWindow(options);
270
+ resolve(window);
271
+ }
272
+ catch (error) {
273
+ log('error', 'create window failed:', error);
274
+ reject(error);
275
+ }
276
+ }
277
+ this.isCreating = false;
278
+ }
279
+ /**
280
+ * 实际的窗口创建逻辑
281
+ */
282
+ async _createWindow(options) {
220
283
  let window;
221
284
  const { usePreload = true, type = 'BW', name = 'anonymous', url, loadingView = { url: undefined }, errorView = { url: undefined }, browserWindow: browserWindowOptions, openDevTools = false, preventOriginClose = false, } = options;
222
285
  options.type = type;
@@ -224,37 +287,46 @@ class WindowsManager {
224
287
  let preloadWin = null;
225
288
  if (type === 'BW' && usePreload && this.preloadWebContentsUrl) {
226
289
  const bwOptions = browserWindowOptions || {};
290
+ console.log(11111, bwOptions);
227
291
  if (bwOptions.frame === false && bwOptions.titleBarStyle === 'hidden') {
228
- preloadWin = this.preloadedBW_FramelessWithButtons;
229
- this.preloadedBW_FramelessWithButtons = null;
230
- setTimeout(() => this._createPreloadBW({ frame: false, transparent: true, titleBarStyle: 'hidden' }), 0);
292
+ if (this.preloadedBW_FramelessWithButtons) {
293
+ preloadWin = this.preloadedBW_FramelessWithButtons;
294
+ this.preloadedBW_FramelessWithButtons = null;
295
+ setTimeout(async () => this.preloadedBW_FramelessWithButtons = await this._createPreloadBW({ frame: false, transparent: true, titleBarStyle: 'hidden' }), 0);
296
+ }
231
297
  }
232
298
  else if (bwOptions.frame === false && bwOptions.titleBarStyle === 'customButtonsOnHover') {
233
- preloadWin = this.preloadedBW_FramelessNoButtons;
234
- this.preloadedBW_FramelessNoButtons = null;
235
- setTimeout(() => this._createPreloadBW({ frame: false, transparent: true, titleBarStyle: 'customButtonsOnHover' }), 0);
299
+ if (this.preloadedBW_FramelessNoButtons) {
300
+ preloadWin = this.preloadedBW_FramelessNoButtons;
301
+ this.preloadedBW_FramelessNoButtons = null;
302
+ setTimeout(async () => this.preloadedBW_FramelessNoButtons = await this._createPreloadBW({ frame: false, transparent: true, titleBarStyle: 'customButtonsOnHover' }), 0);
303
+ }
236
304
  }
237
305
  else {
238
- preloadWin = this.preloadedBW;
239
- this.preloadedBW = null;
240
- setTimeout(() => this._createPreloadBW({}), 0);
306
+ if (this.preloadedBW) {
307
+ preloadWin = this.preloadedBW;
308
+ this.preloadedBW = null;
309
+ setTimeout(async () => this.preloadedBW = await this._createPreloadBW({}), 0);
310
+ }
241
311
  }
242
312
  }
243
313
  if (type === 'BV' && usePreload && this.preloadWebContentsUrl) {
244
- preloadWin = this.preloadedBV;
245
- this.preloadedBV = null;
246
- setTimeout(() => this._createPreloadBV(), 0);
314
+ if (this.preloadedBV) {
315
+ preloadWin = this.preloadedBV;
316
+ this.preloadedBV = null;
317
+ setTimeout(async () => this.preloadedBV = await this._createPreloadBV(), 0);
318
+ }
247
319
  }
248
320
  if (preloadWin) {
249
321
  const win = preloadWin;
250
- log('log', `${name} 使用预加载窗口`, win._id);
322
+ log('log', `${name} 使用预加载窗口(${type})`, win._id);
251
323
  win._type = 'BW';
252
324
  win._name = options.name || 'anonymous';
253
325
  win._extraData = `${options?.extraData || ''}`;
254
326
  win._initUrl = `${options?.url || ''}`;
255
327
  // @ts-ignore
256
- win?.removeAllListeners && win?.removeAllListeners?.();
257
- win.webContents.removeAllListeners && win.webContents.removeAllListeners();
328
+ // win?.removeAllListeners && win?.removeAllListeners?.();
329
+ // win.webContents.removeAllListeners && win.webContents.removeAllListeners();
258
330
  if (type === 'BW') {
259
331
  // @ts-ignore
260
332
  this._applyBrowserWindowOptions(win, options);
@@ -364,7 +436,7 @@ class WindowsManager {
364
436
  if (errorView?.url) {
365
437
  if (type === 'BW') {
366
438
  const showErrorView = lodash.debounce(() => {
367
- const _url = window?.webContents?.getURL?.() || url;
439
+ const _url = window._initUrl;
368
440
  /**
369
441
  * 判断是否是错误视图
370
442
  */
@@ -378,16 +450,37 @@ class WindowsManager {
378
450
  sessionStorage.setItem(key, "${_url}");
379
451
  `);
380
452
  }
381
- }, 300);
453
+ }, 1000);
382
454
  // @ts-ignore
383
455
  window.webContents.on('did-fail-load', (event, errorCode, errorDescription, validatedURL, isMainFrame) => {
384
456
  if (isMainFrame) {
385
457
  showErrorView();
386
458
  }
387
459
  });
460
+ // 当开始加载时取消错误视图
388
461
  window.webContents.on('did-start-loading', () => {
389
462
  showErrorView.cancel();
390
463
  });
464
+ // 当导航开始时取消错误视图
465
+ window.webContents.on('did-start-navigation', () => {
466
+ showErrorView.cancel();
467
+ });
468
+ // 当页面重新加载时取消错误视图
469
+ window.webContents.on('did-navigate', () => {
470
+ showErrorView.cancel();
471
+ });
472
+ // 当页面完成加载时取消错误视图
473
+ window.webContents.on('did-finish-load', () => {
474
+ showErrorView.cancel();
475
+ });
476
+ // 当窗口关闭时取消错误视图
477
+ window.webContents.on('close', () => {
478
+ showErrorView.cancel();
479
+ });
480
+ // 当窗口销毁时取消错误视图
481
+ window.webContents.on('destroyed', () => {
482
+ showErrorView.cancel();
483
+ });
391
484
  }
392
485
  }
393
486
  window.webContents.on('did-attach-webview', (_event, webContents) => {
@@ -469,10 +562,6 @@ class WindowsManager {
469
562
  parentWin?.addBrowserView(window);
470
563
  log('log', 'create - addBrowserView');
471
564
  }
472
- // @ts-ignore
473
- window.loadURL ? window.loadURL(options.url) : window.webContents.loadURL(options.url);
474
- // @ts-ignore
475
- window.focus ? window.focus() : window.webContents.focus();
476
565
  this.windows.set(window.id || window._id || window.webContents.id, window);
477
566
  log('log', 'create', this.windows.keys());
478
567
  // 初始化值
@@ -565,6 +654,13 @@ class WindowsManager {
565
654
  log('error', 'focus', error);
566
655
  }
567
656
  }
657
+ console.log('message xxxx', options.url);
658
+ if (options.url) {
659
+ // @ts-ignore
660
+ window.loadURL ? window.loadURL(options.url) : window.webContents.loadURL(options.url);
661
+ // @ts-ignore
662
+ window.focus ? window.focus() : window.webContents.focus();
663
+ }
568
664
  }
569
665
  catch (error) {
570
666
  log('error', 'create', error);
@@ -848,7 +944,7 @@ class WindowsManager {
848
944
  // 生成一个bv 做为预加载资源窗口,加载完成后销毁
849
945
  async createPreloadWebContents(url) {
850
946
  return new Promise(async (resolve, reject) => {
851
- let bv = this.create({
947
+ let bv = await this.create({
852
948
  type: 'BV',
853
949
  url,
854
950
  name: `preload-web-contents-${md5(url)}`,
@@ -903,7 +999,7 @@ const initialize = (preload, loadingViewUrl, errorViewUrl, preloadWebContentsUrl
903
999
  winInitUrl: `${findWin?._initUrl || ''}`,
904
1000
  };
905
1001
  }
906
- const res = wm.create(opt.data);
1002
+ const res = await wm.create(opt.data);
907
1003
  return {
908
1004
  winId: Number(`${res.id || res._id || -1}`),
909
1005
  winName: `${res?._name || ''}`,