Skip to content

Commit db2c1e1

Browse files
committed
feat: add web container feature
1 parent 54f3ff6 commit db2c1e1

File tree

4 files changed

+70
-13
lines changed

4 files changed

+70
-13
lines changed

package.json

+2
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,8 @@
8888
"electron-log": "^4.4.8",
8989
"electron-store": "^8.1.0",
9090
"electron-updater": "^6.1.4",
91+
"express": "^4.19.2",
92+
"portfinder": "^1.0.32",
9193
"react": "^18.2.0",
9294
"react-dom": "^18.2.0",
9395
"react-router-dom": "^6.16.0"

src/main/plugin.ts

+33-11
Original file line numberDiff line numberDiff line change
@@ -9,9 +9,10 @@ import * as fs from 'fs';
99
import { BrowserWindow, shell, session, app } from 'electron';
1010
import log from 'electron-log';
1111
import Store from 'electron-store';
12+
import axios from 'axios';
13+
import WebContainer from './webContainer';
1214

1315
// import DB from './db';
14-
import axios from 'axios';
1516
import {
1617
deleteFolder,
1718
getAppDir,
@@ -33,10 +34,14 @@ class PluginManager {
3334

3435
private configDir: string = path.join(getAppDir(), 'config');
3536

37+
private container: WebContainer = new WebContainer();
38+
3639
private sortSettingId = 'sortSettingId';
3740

3841
public allPlugins: any[] = [];
3942

43+
private webContainers: Map<string, string> = new Map();
44+
4045
// 创建一个新的存储实例
4146
public store = new Store();
4247

@@ -93,8 +98,8 @@ class PluginManager {
9398
const packageJsonPath = path.join(pluginPath, 'package.json');
9499
const packagePath = path.join(pluginPath, 'plugin.json');
95100
if (fs.existsSync(packagePath)) {
96-
const packageObj = readJsonObjFromFile(packageJsonPath);
97-
const pluginObj = readJsonObjFromFile(packagePath);
101+
const packageObj: any = readJsonObjFromFile(packageJsonPath);
102+
const pluginObj: any = readJsonObjFromFile(packagePath);
98103
if (packageObj) {
99104
pluginObj.name = packageObj.name;
100105
pluginObj.version = packageObj.version;
@@ -116,7 +121,7 @@ class PluginManager {
116121

117122
const { sort } = this.setting.getSetting();
118123
if (sort) {
119-
let sortData = this.store.get(this.sortSettingId, {});
124+
let sortData: any = this.store.get(this.sortSettingId, {});
120125
sortData = new Map(Object.entries(sortData));
121126
if (sortData.size > 0) {
122127
pluginList.sort((a, b) => {
@@ -153,7 +158,10 @@ class PluginManager {
153158
return this.allPlugins.find((plugin) => name === plugin.name);
154159
}
155160

156-
public openPlugin(name: string, pluginViewPool: Map<string, BrowserWindow>) {
161+
public async openPlugin(
162+
name: string,
163+
pluginViewPool: Map<string, BrowserWindow>,
164+
) {
157165
const pluginObj = this.getPlugin(name);
158166
const storeId = `${name}-windowSize`;
159167
const savedSize = this.store.get(storeId, {
@@ -169,7 +177,7 @@ class PluginManager {
169177
const { sort } = this.setting.getSetting();
170178

171179
if (sort) {
172-
let sortData = this.store.get(this.sortSettingId, {});
180+
let sortData: any = this.store.get(this.sortSettingId, {});
173181
sortData = new Map(Object.entries(sortData));
174182
if (sortData.has(name)) {
175183
const click = sortData.get(name);
@@ -201,10 +209,6 @@ class PluginManager {
201209
spellcheck: false,
202210
},
203211
});
204-
// pluginWin.setPosition(
205-
// pluginWin.getPosition()[0],
206-
// pluginWin.getPosition()[1],
207-
// );
208212
pluginWin.on('resize', () => {
209213
const [width, height] = pluginWin?.getSize() || [
210214
DEFAULT_WINDOW_WIDTH,
@@ -213,7 +217,21 @@ class PluginManager {
213217

214218
this.store.set(storeId, { width, height });
215219
});
216-
if (pluginObj.entry && pluginObj.entry.startsWith('http')) {
220+
if (pluginObj.webContainer) {
221+
let url: string;
222+
if (!this.webContainers.has(name)) {
223+
const port = await this.container.listenPlugin(
224+
name,
225+
pluginObj.pluginPath,
226+
);
227+
url = path.join(`http://127.0.0.1:${port}`, pluginObj.entry);
228+
} else {
229+
url = this.webContainers.get(name) as string;
230+
}
231+
232+
pluginWin.loadURL(url);
233+
this.webContainers.set(name, url);
234+
} else if (pluginObj.entry && pluginObj.entry.startsWith('http')) {
217235
pluginWin.loadURL(pluginObj.entry);
218236
} else {
219237
// pluginWin.loadURL(resolveHtmlPath('plugin.html'));
@@ -242,6 +260,10 @@ class PluginManager {
242260
pluginWin.show();
243261
});
244262
pluginWin.on('closed', async () => {
263+
if (pluginObj.webContainer) {
264+
this.webContainers.delete(name);
265+
this.container.closePlugin(name);
266+
}
245267
if (pluginViewPool) {
246268
pluginViewPool.delete(name);
247269
}

src/main/setting.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,7 @@ class Setting {
88

99
private settingPath: string = path.join(this.configDir, 'setting.json');
1010

11-
private setting: object = { sort: true, language: 'china' };
11+
private setting: any = { sort: true, language: 'china' };
1212

1313
constructor() {
1414
this.init();
@@ -34,7 +34,7 @@ class Setting {
3434
return this.setting[key];
3535
}
3636

37-
public getSetting(): object {
37+
public getSetting(): any {
3838
try {
3939
this.setting = readJsonObjFromFile(this.settingPath);
4040
} catch (error) {

src/main/webContainer.ts

+33
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
/* eslint-disable @typescript-eslint/no-unused-vars */
2+
const express = require('express');
3+
const portFinder = require('portfinder');
4+
5+
class WebContainer {
6+
private pluginMap = new Map();
7+
8+
public async listenPlugin(pluginId: string, staticPath: string) {
9+
portFinder.setBasePort(10000);
10+
portFinder.setHighestPort(65535);
11+
const app = express();
12+
const port = await portFinder.getPortPromise();
13+
app.use(express.static(staticPath));
14+
15+
const server = app.listen(port, () => {
16+
console.log(`${pluginId} Server is listening on port ${port}`);
17+
});
18+
this.pluginMap.set(pluginId, server);
19+
20+
return port;
21+
}
22+
23+
public closePlugin(pluginId: string) {
24+
const server = this.pluginMap.get(pluginId);
25+
if (server) {
26+
server.close(() => {
27+
console.log(`${pluginId} Server is closed`);
28+
});
29+
}
30+
}
31+
}
32+
33+
export default WebContainer;

0 commit comments

Comments
 (0)