@lynker-desktop/electron-window-manager 0.0.9-alpha.7 → 0.0.9-alpha.70
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 +53 -2
- package/common/index.d.ts +25 -0
- package/common/index.d.ts.map +1 -1
- package/esm/common/index.d.ts +25 -0
- package/esm/common/index.d.ts.map +1 -1
- package/esm/main/index.d.ts +49 -13
- package/esm/main/index.d.ts.map +1 -1
- package/esm/main/index.js +904 -342
- package/esm/main/index.js.map +1 -1
- package/esm/preload/index.js +17 -2
- package/esm/preload/index.js.map +1 -1
- package/esm/renderer/index.d.ts +5 -5
- package/esm/renderer/index.d.ts.map +1 -1
- package/esm/renderer/index.js +351 -195
- package/esm/renderer/index.js.map +1 -1
- package/main/index.d.ts +49 -13
- package/main/index.d.ts.map +1 -1
- package/main/index.js +911 -349
- package/main/index.js.map +1 -1
- package/package.json +4 -3
- package/preload/index.js +16 -1
- package/preload/index.js.map +1 -1
- package/renderer/index.d.ts +5 -5
- package/renderer/index.d.ts.map +1 -1
- package/renderer/index.js +352 -196
- package/renderer/index.js.map +1 -1
package/renderer/index.js
CHANGED
|
@@ -7,28 +7,37 @@ const eIpc = require('@lynker-desktop/electron-ipc/renderer');
|
|
|
7
7
|
* @author Lynker Desktop Team
|
|
8
8
|
* @version 1.0.0
|
|
9
9
|
*/
|
|
10
|
-
// ==================== 工具函数 ====================
|
|
11
10
|
/**
|
|
12
|
-
*
|
|
13
|
-
*
|
|
14
|
-
*
|
|
15
|
-
* @
|
|
11
|
+
* 通用获取函数:从全局变量或 require 获取模块
|
|
12
|
+
* @param globalKey 全局对象中的键名
|
|
13
|
+
* @param requirePath require 路径
|
|
14
|
+
* @param errorMessage 错误提示信息
|
|
15
|
+
* @returns 获取到的模块或空对象
|
|
16
16
|
*/
|
|
17
|
-
const
|
|
17
|
+
const getModule = (globalKey, requirePath, errorMessage) => {
|
|
18
18
|
try {
|
|
19
19
|
// 优先从全局变量获取(预加载脚本注入)
|
|
20
|
-
const
|
|
21
|
-
if (
|
|
22
|
-
return
|
|
20
|
+
const globalValue = window?.__ELECTRON_WINDOW_MANAGER__?.[globalKey];
|
|
21
|
+
if (globalValue) {
|
|
22
|
+
return globalValue;
|
|
23
23
|
}
|
|
24
24
|
// 回退到 require 方式
|
|
25
|
-
return window?.require(
|
|
25
|
+
return window?.require?.(requirePath);
|
|
26
26
|
}
|
|
27
27
|
catch (error) {
|
|
28
|
-
console.error(
|
|
28
|
+
console.error(errorMessage, error);
|
|
29
29
|
return {};
|
|
30
30
|
}
|
|
31
31
|
};
|
|
32
|
+
/**
|
|
33
|
+
* 获取 IPC 渲染器实例
|
|
34
|
+
* 优先从全局变量获取,回退到 require 方式
|
|
35
|
+
*
|
|
36
|
+
* @returns IpcRenderer 实例或空对象
|
|
37
|
+
*/
|
|
38
|
+
const getIpc = () => {
|
|
39
|
+
return getModule('ipcRenderer', 'electron', '当前非桌面端环境, 请在桌面端中调用');
|
|
40
|
+
};
|
|
32
41
|
/**
|
|
33
42
|
* 获取 Electron Remote 模块
|
|
34
43
|
* 优先从全局变量获取,回退到 require 方式
|
|
@@ -36,55 +45,95 @@ const getIpc = () => {
|
|
|
36
45
|
* @returns RemoteType 实例或空对象
|
|
37
46
|
*/
|
|
38
47
|
const getRemote = () => {
|
|
39
|
-
|
|
40
|
-
// 优先从全局变量获取(预加载脚本注入)
|
|
41
|
-
const globalRemote = window?.__ELECTRON_WINDOW_MANAGER__?.remote;
|
|
42
|
-
if (globalRemote) {
|
|
43
|
-
return globalRemote;
|
|
44
|
-
}
|
|
45
|
-
// 回退到 require 方式
|
|
46
|
-
return window?.require('@electron/remote');
|
|
47
|
-
}
|
|
48
|
-
catch (error) {
|
|
49
|
-
console.error('获取 Remote 模块失败: ', error);
|
|
50
|
-
return {};
|
|
51
|
-
}
|
|
48
|
+
return getModule('remote', '@electron/remote', '获取 Remote 模块失败');
|
|
52
49
|
};
|
|
53
50
|
/**
|
|
54
51
|
* 获取所有窗口的 BrowserView 列表
|
|
55
|
-
* 遍历所有窗口并收集其 BrowserView
|
|
52
|
+
* 遍历所有窗口并收集其 BrowserView(带缓存优化)
|
|
56
53
|
*
|
|
54
|
+
* @param forceRefresh 是否强制刷新缓存
|
|
57
55
|
* @returns BrowserView 数组
|
|
58
56
|
*/
|
|
59
|
-
const getAllBrowserViews = () => {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
const
|
|
63
|
-
|
|
64
|
-
const
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
57
|
+
const getAllBrowserViews = (() => {
|
|
58
|
+
let cachedViews = null;
|
|
59
|
+
let cacheTime = 0;
|
|
60
|
+
const CACHE_DURATION = 100; // 缓存 100ms
|
|
61
|
+
return (forceRefresh = false) => {
|
|
62
|
+
const now = Date.now();
|
|
63
|
+
if (!forceRefresh && cachedViews && (now - cacheTime < CACHE_DURATION)) {
|
|
64
|
+
return cachedViews;
|
|
65
|
+
}
|
|
66
|
+
const remote = getRemote();
|
|
67
|
+
try {
|
|
68
|
+
const allWindows = remote.BrowserWindow?.getAllWindows?.() || [];
|
|
69
|
+
const allBrowserViews = [];
|
|
70
|
+
allWindows.forEach(window => {
|
|
71
|
+
try {
|
|
72
|
+
const views = window.getBrowserViews?.() || [];
|
|
73
|
+
allBrowserViews.push(...views);
|
|
74
|
+
}
|
|
75
|
+
catch (error) {
|
|
76
|
+
// 忽略获取 views 失败的情况
|
|
77
|
+
}
|
|
78
|
+
});
|
|
79
|
+
cachedViews = allBrowserViews;
|
|
80
|
+
cacheTime = now;
|
|
81
|
+
return allBrowserViews;
|
|
82
|
+
}
|
|
83
|
+
catch (error) {
|
|
84
|
+
console.error('获取 BrowserView 列表失败:', error);
|
|
85
|
+
return cachedViews || [];
|
|
86
|
+
}
|
|
87
|
+
};
|
|
88
|
+
})();
|
|
69
89
|
/**
|
|
70
90
|
* 通过 WebContents 查找对应的 BrowserView
|
|
71
91
|
* 如果找不到已挂载的 BrowserView,则创建虚拟的 BrowserView 对象
|
|
72
92
|
*
|
|
73
93
|
* @param webContent - WebContents 实例
|
|
74
|
-
* @returns BVItem
|
|
94
|
+
* @returns BVItem 实例或 null
|
|
75
95
|
*/
|
|
76
96
|
const getBrowserViewByWebContent = (webContent) => {
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
// 如果找到已挂载的 BrowserView,直接返回
|
|
80
|
-
if (existingView) {
|
|
81
|
-
return existingView;
|
|
97
|
+
if (!webContent) {
|
|
98
|
+
return null;
|
|
82
99
|
}
|
|
83
|
-
|
|
84
|
-
|
|
100
|
+
try {
|
|
101
|
+
// 检查 webContents 是否已销毁
|
|
102
|
+
if (webContent.isDestroyed?.()) {
|
|
103
|
+
return null;
|
|
104
|
+
}
|
|
105
|
+
// 查找已挂载的 BrowserView
|
|
106
|
+
const allBrowserViews = getAllBrowserViews();
|
|
107
|
+
const existingView = allBrowserViews.find(view => view.webContents === webContent);
|
|
108
|
+
if (existingView) {
|
|
109
|
+
return existingView;
|
|
110
|
+
}
|
|
111
|
+
// 如果 WebContents 存在但未挂载到窗口,创建虚拟 BrowserView
|
|
85
112
|
return createVirtualBrowserView(webContent);
|
|
86
113
|
}
|
|
87
|
-
|
|
114
|
+
catch (error) {
|
|
115
|
+
console.error('获取 BrowserView 失败:', error);
|
|
116
|
+
return null;
|
|
117
|
+
}
|
|
118
|
+
};
|
|
119
|
+
/**
|
|
120
|
+
* 统一的 IPC 调用封装
|
|
121
|
+
* @param type IPC 消息类型
|
|
122
|
+
* @param data IPC 消息数据
|
|
123
|
+
* @returns Promise<T> IPC 调用结果
|
|
124
|
+
*/
|
|
125
|
+
const invokeIpc = async (type, data) => {
|
|
126
|
+
try {
|
|
127
|
+
const ipc = getIpc();
|
|
128
|
+
if (!ipc || !ipc.invoke) {
|
|
129
|
+
throw new Error('IPC 不可用');
|
|
130
|
+
}
|
|
131
|
+
return await ipc.invoke('__ELECTRON_WINDOW_MANAGER_IPC_CHANNEL__', { type, data });
|
|
132
|
+
}
|
|
133
|
+
catch (error) {
|
|
134
|
+
console.error(`IPC 调用失败 [${type}]:`, error);
|
|
135
|
+
throw error;
|
|
136
|
+
}
|
|
88
137
|
};
|
|
89
138
|
/**
|
|
90
139
|
* 创建虚拟的 BrowserView 对象
|
|
@@ -94,37 +143,37 @@ const getBrowserViewByWebContent = (webContent) => {
|
|
|
94
143
|
* @returns 虚拟的 BVItem 对象
|
|
95
144
|
*/
|
|
96
145
|
const createVirtualBrowserView = (webContent) => {
|
|
146
|
+
const webContentId = webContent.id;
|
|
97
147
|
const virtualView = {
|
|
98
|
-
id:
|
|
99
|
-
_id:
|
|
148
|
+
id: webContentId,
|
|
149
|
+
_id: webContentId,
|
|
100
150
|
_type: 'BV',
|
|
101
151
|
_name: '',
|
|
102
152
|
_extraData: '',
|
|
103
153
|
webContents: webContent,
|
|
104
154
|
// 代理方法,通过 IPC 调用主进程
|
|
105
155
|
getBounds: async () => {
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
156
|
+
return invokeIpc('borrowView_getBounds', {
|
|
157
|
+
webContentId,
|
|
158
|
+
options: {}
|
|
109
159
|
});
|
|
110
|
-
return result;
|
|
111
160
|
},
|
|
112
161
|
setBounds: async (bounds) => {
|
|
113
|
-
return
|
|
114
|
-
|
|
115
|
-
|
|
162
|
+
return invokeIpc('borrowView_setBounds', {
|
|
163
|
+
webContentId,
|
|
164
|
+
options: bounds
|
|
116
165
|
});
|
|
117
166
|
},
|
|
118
167
|
setAutoResize: async (autoResize) => {
|
|
119
|
-
return
|
|
120
|
-
|
|
121
|
-
|
|
168
|
+
return invokeIpc('borrowView_setAutoResize', {
|
|
169
|
+
webContentId,
|
|
170
|
+
options: autoResize
|
|
122
171
|
});
|
|
123
172
|
},
|
|
124
173
|
setBackgroundColor: async (color) => {
|
|
125
|
-
return
|
|
126
|
-
|
|
127
|
-
|
|
174
|
+
return invokeIpc('borrowView_setBackgroundColor', {
|
|
175
|
+
webContentId,
|
|
176
|
+
options: color
|
|
128
177
|
});
|
|
129
178
|
},
|
|
130
179
|
};
|
|
@@ -137,34 +186,107 @@ const createVirtualBrowserView = (webContent) => {
|
|
|
137
186
|
* @param data - 窗口数据
|
|
138
187
|
*/
|
|
139
188
|
const setWindowProperties = (window, data) => {
|
|
140
|
-
if (!window)
|
|
189
|
+
if (!window || !data)
|
|
141
190
|
return;
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
191
|
+
try {
|
|
192
|
+
window._name = data.winName || '';
|
|
193
|
+
window._type = data.winType || '';
|
|
194
|
+
window._extraData = data.winExtraData || '';
|
|
195
|
+
window._initUrl = data.winInitUrl || '';
|
|
196
|
+
window._zIndex = data.winZIndex ?? 0;
|
|
197
|
+
// 尝试设置 ID
|
|
198
|
+
if (data.winId) {
|
|
199
|
+
try {
|
|
200
|
+
window.id = Number(data.winId);
|
|
201
|
+
}
|
|
202
|
+
catch (error) {
|
|
203
|
+
// 忽略设置 ID 失败的情况
|
|
204
|
+
}
|
|
205
|
+
}
|
|
206
|
+
}
|
|
207
|
+
catch (error) {
|
|
208
|
+
console.error('设置窗口属性失败:', error);
|
|
209
|
+
}
|
|
146
210
|
};
|
|
147
|
-
|
|
211
|
+
/**
|
|
212
|
+
* 根据 webContents ID 查找窗口实例
|
|
213
|
+
* 通过 webContents 查找对应的 BrowserWindow 或 BrowserView
|
|
214
|
+
* 如果是 webview,则找到它的父 BrowserWindow
|
|
215
|
+
*
|
|
216
|
+
* @param webContentsId - webContents ID
|
|
217
|
+
* @returns 窗口实例或 null
|
|
218
|
+
*/
|
|
219
|
+
const findWindowById = (webContentsId) => {
|
|
220
|
+
if (!webContentsId || webContentsId <= 0) {
|
|
221
|
+
return null;
|
|
222
|
+
}
|
|
148
223
|
const remote = getRemote();
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
const
|
|
159
|
-
|
|
160
|
-
|
|
224
|
+
try {
|
|
225
|
+
// 首先通过 webContentsId 获取 webContents
|
|
226
|
+
const webContent = remote.webContents?.fromId?.(webContentsId);
|
|
227
|
+
if (!webContent) {
|
|
228
|
+
return null;
|
|
229
|
+
}
|
|
230
|
+
// Case 1: 查找 BrowserView
|
|
231
|
+
// 遍历所有窗口的 BrowserView,查找匹配的
|
|
232
|
+
const allWindows = remote.BrowserWindow?.getAllWindows?.() || [];
|
|
233
|
+
for (const win of allWindows) {
|
|
234
|
+
try {
|
|
235
|
+
const views = win.getBrowserViews?.() || [];
|
|
236
|
+
for (const view of views) {
|
|
237
|
+
if (view.webContents?.id === webContentsId) {
|
|
238
|
+
return view;
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
}
|
|
242
|
+
catch (error) {
|
|
243
|
+
// 忽略获取 views 失败的情况
|
|
244
|
+
}
|
|
245
|
+
}
|
|
246
|
+
// Case 2: WebView
|
|
247
|
+
// webview 有 hostWebContents,指向它所在的 BrowserWindow 的 webContents
|
|
248
|
+
if (webContent.hostWebContents) {
|
|
249
|
+
const parentWindow = remote.BrowserWindow?.fromWebContents?.(webContent.hostWebContents);
|
|
250
|
+
if (parentWindow) {
|
|
251
|
+
return parentWindow;
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
// Case 3: 普通 BrowserWindow 本身
|
|
255
|
+
const browserWindow = remote.BrowserWindow?.fromWebContents?.(webContent);
|
|
256
|
+
if (browserWindow) {
|
|
257
|
+
return browserWindow;
|
|
161
258
|
}
|
|
259
|
+
// Case 4: 如果找不到已挂载的 BrowserView,尝试创建虚拟 BrowserView
|
|
260
|
+
return getBrowserViewByWebContent(webContent);
|
|
162
261
|
}
|
|
163
|
-
|
|
164
|
-
|
|
262
|
+
catch (error) {
|
|
263
|
+
console.error(`查找窗口失败 [${webContentsId}]:`, error);
|
|
264
|
+
}
|
|
265
|
+
return null;
|
|
266
|
+
};
|
|
267
|
+
async function create(options) {
|
|
268
|
+
try {
|
|
269
|
+
// 通过 IPC 调用主进程创建窗口
|
|
270
|
+
const data = await eIpc.RendererIPC.invokeMain('__ELECTRON_WINDOW_MANAGER_IPC_CHANNEL__', {
|
|
271
|
+
type: 'create',
|
|
272
|
+
data: options
|
|
273
|
+
});
|
|
274
|
+
if (!data?.winId) {
|
|
275
|
+
throw new Error('创建窗口失败: 未返回有效的窗口 ID');
|
|
276
|
+
}
|
|
277
|
+
// 查找窗口实例
|
|
278
|
+
const window = findWindowById(data.winId);
|
|
279
|
+
if (!window) {
|
|
280
|
+
throw new Error(`创建窗口失败: 无法找到窗口实例 [${data.winId}]`);
|
|
281
|
+
}
|
|
282
|
+
// 设置窗口属性
|
|
165
283
|
setWindowProperties(window, data);
|
|
284
|
+
return window;
|
|
285
|
+
}
|
|
286
|
+
catch (error) {
|
|
287
|
+
console.error('创建窗口失败:', error);
|
|
288
|
+
throw error;
|
|
166
289
|
}
|
|
167
|
-
return window;
|
|
168
290
|
}
|
|
169
291
|
/**
|
|
170
292
|
* 获取当前窗口实例
|
|
@@ -174,7 +296,7 @@ async function create(options) {
|
|
|
174
296
|
const getCurrentWindow = async () => {
|
|
175
297
|
const remote = getRemote();
|
|
176
298
|
const currentWindow = remote.getCurrentWindow();
|
|
177
|
-
return await get(currentWindow
|
|
299
|
+
return await get(currentWindow?.webContents?.id);
|
|
178
300
|
};
|
|
179
301
|
/**
|
|
180
302
|
* 根据 ID 或名称获取窗口
|
|
@@ -192,85 +314,70 @@ const getCurrentWindow = async () => {
|
|
|
192
314
|
* ```
|
|
193
315
|
*/
|
|
194
316
|
const get = async (idOrName) => {
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
});
|
|
201
|
-
// 尝试通过 ID 获取窗口
|
|
202
|
-
let window = remote.BrowserWindow.fromId(data.winId);
|
|
203
|
-
// 如果不是 BrowserWindow,尝试获取 BrowserView
|
|
204
|
-
if (!window) {
|
|
205
|
-
const webContent = remote.webContents.fromId(data.winId);
|
|
206
|
-
if (webContent) {
|
|
207
|
-
window = getBrowserViewByWebContent(webContent);
|
|
317
|
+
try {
|
|
318
|
+
// 通过 IPC 获取窗口信息
|
|
319
|
+
const data = await invokeIpc('get', idOrName);
|
|
320
|
+
if (!data?.winId) {
|
|
321
|
+
return undefined;
|
|
208
322
|
}
|
|
323
|
+
// 查找窗口实例
|
|
324
|
+
const window = findWindowById(data.winId);
|
|
325
|
+
if (window) {
|
|
326
|
+
setWindowProperties(window, data);
|
|
327
|
+
}
|
|
328
|
+
return window || undefined;
|
|
209
329
|
}
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
330
|
+
catch (error) {
|
|
331
|
+
console.error('获取窗口失败:', error);
|
|
332
|
+
return undefined;
|
|
213
333
|
}
|
|
214
|
-
return window;
|
|
215
334
|
};
|
|
216
335
|
async function getAll(type) {
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
});
|
|
223
|
-
const allWindows = new Map();
|
|
224
|
-
const browserWindows = new Map();
|
|
225
|
-
const browserViews = new Map();
|
|
226
|
-
const allBrowserWindows = remote.BrowserWindow.getAllWindows();
|
|
227
|
-
// 遍历窗口数据
|
|
228
|
-
for (const key in windowData) {
|
|
229
|
-
const element = windowData[key];
|
|
230
|
-
let window;
|
|
231
|
-
// 尝试在 BrowserWindow 中查找
|
|
232
|
-
window = allBrowserWindows.find(win => `${win.id}` === `${element?.winId}`);
|
|
233
|
-
// 如果不是 BrowserWindow,尝试获取 BrowserView
|
|
234
|
-
if (!window) {
|
|
235
|
-
const webContent = remote.webContents.fromId(element.winId);
|
|
236
|
-
if (webContent) {
|
|
237
|
-
window = getBrowserViewByWebContent(webContent);
|
|
238
|
-
}
|
|
336
|
+
try {
|
|
337
|
+
// 通过 IPC 获取所有窗口信息
|
|
338
|
+
const windowData = await invokeIpc('getAll', undefined);
|
|
339
|
+
if (!windowData || typeof windowData !== 'object') {
|
|
340
|
+
return new Map();
|
|
239
341
|
}
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
setWindowProperties(window, {
|
|
249
|
-
winId: element.winId,
|
|
250
|
-
winName: element.winName,
|
|
251
|
-
winType: element.winType,
|
|
252
|
-
winExtraData: element.winExtraData,
|
|
253
|
-
winInitUrl: element.winInitUrl
|
|
254
|
-
});
|
|
255
|
-
const windowId = window.id || window._id;
|
|
256
|
-
allWindows.set(windowId, window);
|
|
257
|
-
// 按类型分类
|
|
258
|
-
if (window._type === 'BW') {
|
|
259
|
-
browserWindows.set(windowId, window);
|
|
342
|
+
const allWindows = new Map();
|
|
343
|
+
const browserWindows = new Map();
|
|
344
|
+
const browserViews = new Map();
|
|
345
|
+
// 遍历窗口数据
|
|
346
|
+
for (const key in windowData) {
|
|
347
|
+
const element = windowData[key];
|
|
348
|
+
if (!element?.winId) {
|
|
349
|
+
continue;
|
|
260
350
|
}
|
|
261
|
-
|
|
262
|
-
|
|
351
|
+
// 查找窗口实例
|
|
352
|
+
const window = findWindowById(element.winId);
|
|
353
|
+
if (window) {
|
|
354
|
+
// 设置窗口属性
|
|
355
|
+
setWindowProperties(window, element);
|
|
356
|
+
// 统一使用 webContents.id 作为键
|
|
357
|
+
const windowId = window.webContents?.id || element.winId;
|
|
358
|
+
allWindows.set(windowId, window);
|
|
359
|
+
// 按类型分类
|
|
360
|
+
if (window._type === 'BW') {
|
|
361
|
+
browserWindows.set(windowId, window);
|
|
362
|
+
}
|
|
363
|
+
else if (window._type === 'BV') {
|
|
364
|
+
browserViews.set(windowId, window);
|
|
365
|
+
}
|
|
263
366
|
}
|
|
264
367
|
}
|
|
368
|
+
// 根据类型返回对应的映射表
|
|
369
|
+
if (type === 'BW') {
|
|
370
|
+
return browserWindows;
|
|
371
|
+
}
|
|
372
|
+
if (type === 'BV') {
|
|
373
|
+
return browserViews;
|
|
374
|
+
}
|
|
375
|
+
return allWindows;
|
|
265
376
|
}
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
return
|
|
269
|
-
}
|
|
270
|
-
if (type === 'BV') {
|
|
271
|
-
return browserViews;
|
|
377
|
+
catch (error) {
|
|
378
|
+
console.error('获取所有窗口失败:', error);
|
|
379
|
+
return new Map();
|
|
272
380
|
}
|
|
273
|
-
return allWindows;
|
|
274
381
|
}
|
|
275
382
|
/**
|
|
276
383
|
* 关闭指定窗口
|
|
@@ -279,11 +386,14 @@ async function getAll(type) {
|
|
|
279
386
|
* @returns Promise<boolean> 操作是否成功
|
|
280
387
|
*/
|
|
281
388
|
const close = async (idOrName) => {
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
}
|
|
286
|
-
|
|
389
|
+
try {
|
|
390
|
+
await invokeIpc('close', idOrName);
|
|
391
|
+
return true;
|
|
392
|
+
}
|
|
393
|
+
catch (error) {
|
|
394
|
+
console.error('关闭窗口失败:', error);
|
|
395
|
+
return false;
|
|
396
|
+
}
|
|
287
397
|
};
|
|
288
398
|
/**
|
|
289
399
|
* 关闭所有窗口
|
|
@@ -291,11 +401,14 @@ const close = async (idOrName) => {
|
|
|
291
401
|
* @returns Promise<boolean> 操作是否成功
|
|
292
402
|
*/
|
|
293
403
|
const closeAll = async () => {
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
}
|
|
298
|
-
|
|
404
|
+
try {
|
|
405
|
+
await invokeIpc('closeAll', undefined);
|
|
406
|
+
return true;
|
|
407
|
+
}
|
|
408
|
+
catch (error) {
|
|
409
|
+
console.error('关闭所有窗口失败:', error);
|
|
410
|
+
return false;
|
|
411
|
+
}
|
|
299
412
|
};
|
|
300
413
|
/**
|
|
301
414
|
* 根据 WebContents ID 查找对应的窗口
|
|
@@ -303,12 +416,18 @@ const closeAll = async () => {
|
|
|
303
416
|
* @param webContentId - WebContents ID
|
|
304
417
|
* @returns Promise<BWItem | BVItem | undefined> 窗口实例
|
|
305
418
|
*/
|
|
306
|
-
const
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
419
|
+
const getWindowForWebContentsId = async (webContentId) => {
|
|
420
|
+
try {
|
|
421
|
+
const winId = await invokeIpc('getWindowForWebContentsId', webContentId);
|
|
422
|
+
if (!winId) {
|
|
423
|
+
return undefined;
|
|
424
|
+
}
|
|
425
|
+
return get(winId);
|
|
426
|
+
}
|
|
427
|
+
catch (error) {
|
|
428
|
+
console.error('根据 WebContents ID 查找窗口失败:', error);
|
|
429
|
+
return undefined;
|
|
430
|
+
}
|
|
312
431
|
};
|
|
313
432
|
/**
|
|
314
433
|
* 重命名窗口
|
|
@@ -318,11 +437,17 @@ const getWindowForWebContentId = async (webContentId) => {
|
|
|
318
437
|
* @returns Promise<BWItem | BVItem | undefined> 重命名后的窗口实例
|
|
319
438
|
*/
|
|
320
439
|
const rename = async (idOrName, newName) => {
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
data
|
|
324
|
-
|
|
325
|
-
|
|
440
|
+
try {
|
|
441
|
+
const data = await invokeIpc('rename', { idOrName, newName });
|
|
442
|
+
if (!data?.winId) {
|
|
443
|
+
return undefined;
|
|
444
|
+
}
|
|
445
|
+
return get(data.winId);
|
|
446
|
+
}
|
|
447
|
+
catch (error) {
|
|
448
|
+
console.error('重命名窗口失败:', error);
|
|
449
|
+
return undefined;
|
|
450
|
+
}
|
|
326
451
|
};
|
|
327
452
|
/**
|
|
328
453
|
* 重置窗口初始化URL
|
|
@@ -332,22 +457,31 @@ const rename = async (idOrName, newName) => {
|
|
|
332
457
|
* @returns Promise<BWItem | BVItem | undefined> 重置后的窗口实例
|
|
333
458
|
*/
|
|
334
459
|
const reInitUrl = async (idOrName, url) => {
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
data
|
|
338
|
-
|
|
339
|
-
|
|
460
|
+
try {
|
|
461
|
+
const data = await invokeIpc('reInitUrl', { idOrName, url });
|
|
462
|
+
if (!data?.winId) {
|
|
463
|
+
return undefined;
|
|
464
|
+
}
|
|
465
|
+
return get(data.winId);
|
|
466
|
+
}
|
|
467
|
+
catch (error) {
|
|
468
|
+
console.error('重置窗口 URL 失败:', error);
|
|
469
|
+
return undefined;
|
|
470
|
+
}
|
|
340
471
|
};
|
|
341
472
|
/**
|
|
342
|
-
* 设置预加载 WebContents
|
|
473
|
+
* 设置预加载 WebContents 配置
|
|
343
474
|
*
|
|
344
|
-
* @param
|
|
475
|
+
* @param preloadWebContentsConfig - 预加载配置
|
|
345
476
|
*/
|
|
346
|
-
const
|
|
347
|
-
|
|
348
|
-
|
|
349
|
-
|
|
350
|
-
|
|
477
|
+
const setPreloadWebContentsConfig = async (preloadWebContentsConfig) => {
|
|
478
|
+
try {
|
|
479
|
+
await invokeIpc('setPreloadWebContentsConfig', preloadWebContentsConfig);
|
|
480
|
+
}
|
|
481
|
+
catch (error) {
|
|
482
|
+
console.error('设置预加载配置失败:', error);
|
|
483
|
+
throw error;
|
|
484
|
+
}
|
|
351
485
|
};
|
|
352
486
|
/**
|
|
353
487
|
* 获取预加载脚本路径
|
|
@@ -356,24 +490,46 @@ const setPreloadWebContentsUrl = async (preloadWebContentsUrl) => {
|
|
|
356
490
|
* @returns Promise<string | undefined> 预加载脚本路径
|
|
357
491
|
*/
|
|
358
492
|
const getPreload = (() => {
|
|
359
|
-
let cachedPreload =
|
|
493
|
+
let cachedPreload = null;
|
|
494
|
+
let isLoading = false;
|
|
495
|
+
let loadPromise = null;
|
|
360
496
|
return async () => {
|
|
361
497
|
// 如果已有缓存,直接返回
|
|
362
|
-
if (cachedPreload !==
|
|
498
|
+
if (cachedPreload !== null) {
|
|
363
499
|
return cachedPreload;
|
|
364
500
|
}
|
|
365
|
-
//
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
501
|
+
// 如果正在加载,返回同一个 Promise
|
|
502
|
+
if (isLoading && loadPromise) {
|
|
503
|
+
return loadPromise;
|
|
504
|
+
}
|
|
505
|
+
// 开始加载
|
|
506
|
+
isLoading = true;
|
|
507
|
+
loadPromise = (async () => {
|
|
508
|
+
try {
|
|
509
|
+
// 通过 IPC 获取预加载脚本路径
|
|
510
|
+
const data = await invokeIpc('getPreload', undefined);
|
|
511
|
+
// 缓存结果(即使是 undefined 也缓存,避免重复请求)
|
|
512
|
+
cachedPreload = data;
|
|
513
|
+
return data;
|
|
514
|
+
}
|
|
515
|
+
catch (error) {
|
|
516
|
+
console.error('获取预加载脚本路径失败:', error);
|
|
517
|
+
// 失败时也缓存 null,避免重复请求
|
|
518
|
+
cachedPreload = undefined;
|
|
519
|
+
return undefined;
|
|
520
|
+
}
|
|
521
|
+
finally {
|
|
522
|
+
isLoading = false;
|
|
523
|
+
loadPromise = null;
|
|
524
|
+
}
|
|
525
|
+
})();
|
|
526
|
+
return loadPromise;
|
|
373
527
|
};
|
|
374
528
|
})();
|
|
375
|
-
//
|
|
376
|
-
getPreload()
|
|
529
|
+
// 初始化时异步获取预加载脚本(不阻塞)
|
|
530
|
+
getPreload().catch(() => {
|
|
531
|
+
// 静默处理初始化失败
|
|
532
|
+
});
|
|
377
533
|
// ==================== 开发工具相关(已注释) ====================
|
|
378
534
|
/*
|
|
379
535
|
* 开发工具相关功能(已注释,可根据需要启用)
|
|
@@ -400,8 +556,8 @@ exports.get = get;
|
|
|
400
556
|
exports.getAll = getAll;
|
|
401
557
|
exports.getCurrentWindow = getCurrentWindow;
|
|
402
558
|
exports.getPreload = getPreload;
|
|
403
|
-
exports.
|
|
559
|
+
exports.getWindowForWebContentsId = getWindowForWebContentsId;
|
|
404
560
|
exports.reInitUrl = reInitUrl;
|
|
405
561
|
exports.rename = rename;
|
|
406
|
-
exports.
|
|
562
|
+
exports.setPreloadWebContentsConfig = setPreloadWebContentsConfig;
|
|
407
563
|
//# sourceMappingURL=index.js.map
|