nexfep 0.5.4 → 0.6.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-CN.md +122 -75
- package/README.md +122 -75
- package/frontend/index.d.ts +19 -19
- package/package.json +14 -8
- package/src/Application.d.ts +7 -4
- package/src/Application.js +4 -3
- package/src/Icon.d.ts +19 -0
- package/src/Icon.js +36 -0
- package/src/Logger.d.ts +1 -0
- package/src/Logger.js +5 -14
- package/src/Tray.d.ts +4 -3
- package/src/Tray.js +3 -3
- package/src/WindowManager.d.ts +16 -2
- package/src/WindowManager.js +45 -6
package/README-CN.md
CHANGED
|
@@ -41,7 +41,10 @@ import { Application } from "nexfep";
|
|
|
41
41
|
|
|
42
42
|
const app = new Application();
|
|
43
43
|
|
|
44
|
-
const window = await app.windows.createWindow(
|
|
44
|
+
const window = await app.windows.createWindow({
|
|
45
|
+
visible: true,
|
|
46
|
+
decoration: false,
|
|
47
|
+
});
|
|
45
48
|
|
|
46
49
|
await window.loadHTML("<h1 nexfep-area-drag>Hello Nexfep!</h1>");
|
|
47
50
|
```
|
|
@@ -81,11 +84,37 @@ const app = new Application({ LogFilePath: "./app.log" });
|
|
|
81
84
|
- `createLocker(appName)` — 创建应用实例锁,防止多个实例运行
|
|
82
85
|
- `exit()` — 退出应用
|
|
83
86
|
|
|
87
|
+
### Icon
|
|
88
|
+
|
|
89
|
+
`Icon` 用于表示图片资源,可被用作窗口图标、托盘图标等。
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { Icon } from "nexfep";
|
|
93
|
+
|
|
94
|
+
// 从文件路径创建
|
|
95
|
+
const icon = Icon.from("./icon.png");
|
|
96
|
+
|
|
97
|
+
// 从 Buffer 或 Uint8Array 创建
|
|
98
|
+
const icon = Icon.from(buffer);
|
|
99
|
+
const icon = Icon.from(uint8Array);
|
|
100
|
+
|
|
101
|
+
// 从包含 data/width/height 的对象创建
|
|
102
|
+
const icon = Icon.from({ data: buffer, width: 64, height: 64 });
|
|
103
|
+
const icon = Icon.from({ data: uint8Array, width: 64, height: 64 });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**静态方法**
|
|
107
|
+
|
|
108
|
+
| 方法 | 参数 | 返回值 | 说明 |
|
|
109
|
+
| ------------------ | ----------------------------------------------------------------------------------------- | ------ | ---------------- |
|
|
110
|
+
| `Icon.from(input)` | `string` \| `Buffer` \| `Uint8Array` \| `{ data: Uint8Array \| Buffer, width?, height? }` | `Icon` | 创建一个图标实例 |
|
|
111
|
+
|
|
84
112
|
### Logger
|
|
85
113
|
|
|
86
114
|
Logger 支持文件输出和彩色控制台输出,可通过 `app.logger` 访问。
|
|
87
115
|
|
|
88
116
|
```typescript
|
|
117
|
+
app.logger.clear();
|
|
89
118
|
app.logger.log("Hello World");
|
|
90
119
|
app.logger.error("发生错误");
|
|
91
120
|
app.logger.warn("警告信息");
|
|
@@ -95,13 +124,14 @@ app.logger.debug("调试信息");
|
|
|
95
124
|
|
|
96
125
|
**方法**
|
|
97
126
|
|
|
98
|
-
| 方法 | 说明
|
|
99
|
-
| ---------------- |
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
127
|
+
| 方法 | 说明 |
|
|
128
|
+
| ---------------- | ------------------------------------------------- |
|
|
129
|
+
| `clear()` | 清空日志文件(仅在设置了`LogFilePath`参数时生效) |
|
|
130
|
+
| `log(message)` | 记录日志 |
|
|
131
|
+
| `error(message)` | 记录错误日志(红色) |
|
|
132
|
+
| `warn(message)` | 记录警告日志(黄色) |
|
|
133
|
+
| `info(message)` | 记录提示日志(蓝色) |
|
|
134
|
+
| `debug(message)` | 记录调试日志(灰色) |
|
|
105
135
|
|
|
106
136
|
每个方法接受字符串或字符串数组作为参数。
|
|
107
137
|
|
|
@@ -145,16 +175,14 @@ locker.unlock();
|
|
|
145
175
|
通过 `app.createTray()` 创建和管理系统托盘图标及右键菜单。
|
|
146
176
|
|
|
147
177
|
```typescript
|
|
148
|
-
import {
|
|
178
|
+
import { Icon } from "nexfep";
|
|
179
|
+
|
|
180
|
+
const icon = Icon.from("./icon.png");
|
|
149
181
|
|
|
150
182
|
const tray = app.createTray({
|
|
151
183
|
id: "my-tray",
|
|
152
184
|
tooltip: "我的应用",
|
|
153
|
-
icon:
|
|
154
|
-
data: readFileSync("./icon.png"),
|
|
155
|
-
width: 32,
|
|
156
|
-
height: 32,
|
|
157
|
-
},
|
|
185
|
+
icon: icon, // Icon 实例
|
|
158
186
|
menuItems: [
|
|
159
187
|
{ id: "show", label: "显示窗口" },
|
|
160
188
|
{ id: "quit", label: "退出" },
|
|
@@ -162,29 +190,19 @@ const tray = app.createTray({
|
|
|
162
190
|
});
|
|
163
191
|
```
|
|
164
192
|
|
|
165
|
-
`icon` 字段接受 `TrayIconImage` 对象:
|
|
166
|
-
|
|
167
|
-
```typescript
|
|
168
|
-
interface TrayIconImage {
|
|
169
|
-
data: Buffer; // 图片二进制数据
|
|
170
|
-
width?: number; // 可选宽度
|
|
171
|
-
height?: number; // 可选高度
|
|
172
|
-
}
|
|
173
|
-
```
|
|
174
|
-
|
|
175
193
|
**方法**
|
|
176
194
|
|
|
177
|
-
| 方法
|
|
178
|
-
|
|
|
179
|
-
| `addMenuItem(item)`
|
|
180
|
-
| `removeMenuItem(id)`
|
|
181
|
-
| `setMenuItems(items)`
|
|
182
|
-
| `setIcon(icon
|
|
183
|
-
| `setTooltip(tooltip)`
|
|
184
|
-
| `on(event, callback)`
|
|
185
|
-
| `show()`
|
|
186
|
-
| `hide()`
|
|
187
|
-
| `destroy()`
|
|
195
|
+
| 方法 | 描述 |
|
|
196
|
+
| --------------------- | ------------------------------ |
|
|
197
|
+
| `addMenuItem(item)` | 添加菜单项 |
|
|
198
|
+
| `removeMenuItem(id)` | 按 ID 删除菜单项 |
|
|
199
|
+
| `setMenuItems(items)` | 替换所有菜单项 |
|
|
200
|
+
| `setIcon(icon)` | 更改托盘图标,接受 `Icon` 实例 |
|
|
201
|
+
| `setTooltip(tooltip)` | 更改悬停提示文本 |
|
|
202
|
+
| `on(event, callback)` | 监听托盘事件(如 `'click'`) |
|
|
203
|
+
| `show()` | 显示托盘图标 |
|
|
204
|
+
| `hide()` | 隐藏托盘图标 |
|
|
205
|
+
| `destroy()` | 销毁托盘图标 |
|
|
188
206
|
|
|
189
207
|
```typescript
|
|
190
208
|
tray.on("click", () => {
|
|
@@ -199,13 +217,14 @@ tray.setTooltip("Nexfep 应用");
|
|
|
199
217
|
通过 `app.utils.notify()` 发送桌面通知。
|
|
200
218
|
|
|
201
219
|
```typescript
|
|
202
|
-
const notification = app.utils.notify("标题", "通知内容");
|
|
220
|
+
const notification = app.utils.notify("标题", { body: "通知内容" });
|
|
203
221
|
```
|
|
204
222
|
|
|
205
223
|
**参数**
|
|
206
224
|
|
|
207
225
|
- `title` — 通知标题
|
|
208
|
-
- `
|
|
226
|
+
- `options`(可选)— 配置对象
|
|
227
|
+
- `body` — 通知正文
|
|
209
228
|
|
|
210
229
|
### 窗口池
|
|
211
230
|
|
|
@@ -218,13 +237,38 @@ const pool = app.windows;
|
|
|
218
237
|
### 窗口创建
|
|
219
238
|
|
|
220
239
|
```typescript
|
|
221
|
-
|
|
240
|
+
// 不传参数使用全部默认值
|
|
241
|
+
const win = await pool.createWindow();
|
|
242
|
+
|
|
243
|
+
// 传入部分参数
|
|
244
|
+
const win = await pool.createWindow({
|
|
245
|
+
visible: true,
|
|
246
|
+
title: "我的应用",
|
|
247
|
+
});
|
|
248
|
+
|
|
249
|
+
// 全部参数
|
|
250
|
+
const win = await pool.createWindow({
|
|
251
|
+
visible: true, // 是否立即显示,默认 true
|
|
252
|
+
decoration: true, // 是否使用系统装饰,默认 true
|
|
253
|
+
title: "我的应用", // 窗口标题,默认 "Nexfep Window"
|
|
254
|
+
icon: iconInstance, // 窗口图标,Icon 实例,可选
|
|
255
|
+
resizable: true, // 是否可调整大小,默认 true
|
|
256
|
+
width: 800, // 窗口宽度,默认 800
|
|
257
|
+
height: 600, // 窗口高度,默认 600
|
|
258
|
+
});
|
|
222
259
|
```
|
|
223
260
|
|
|
224
261
|
**参数说明**
|
|
225
262
|
|
|
226
|
-
|
|
227
|
-
|
|
263
|
+
| 选项 | 类型 | 默认值 | 说明 |
|
|
264
|
+
| ------------ | --------- | ----------------- | ------------------------------------------------------------------- |
|
|
265
|
+
| `visible` | `boolean` | `true` | 是否立即显示窗口 |
|
|
266
|
+
| `decoration` | `boolean` | `true` | 是否使用系统窗口装饰。设为 `false` 时,窗口无边框,需要自定义标题栏 |
|
|
267
|
+
| `title` | `string` | `"Nexfep Window"` | 窗口标题 |
|
|
268
|
+
| `icon` | `Icon` | 无 | 窗口图标 |
|
|
269
|
+
| `resizable` | `boolean` | `true` | 窗口是否可调整大小 |
|
|
270
|
+
| `width` | `number` | `800` | 窗口宽度(像素) |
|
|
271
|
+
| `height` | `number` | `600` | 窗口高度(像素) |
|
|
228
272
|
|
|
229
273
|
### 窗口操作
|
|
230
274
|
|
|
@@ -586,44 +630,47 @@ nexfep build -u 7
|
|
|
586
630
|
|
|
587
631
|
### WindowPool
|
|
588
632
|
|
|
589
|
-
| 方法/属性
|
|
590
|
-
|
|
|
591
|
-
| `createWindow(
|
|
592
|
-
| `handle(event, callback)`
|
|
593
|
-
| `unhandle(event, callback)`
|
|
594
|
-
| `global`
|
|
595
|
-
| `closeWindow(window)`
|
|
596
|
-
| `onCustomMessage`
|
|
633
|
+
| 方法/属性 | 参数 | 返回值 | 说明 |
|
|
634
|
+
| --------------------------- | ----------------------------------------------- | ----------------- | ------------------------ |
|
|
635
|
+
| `createWindow(options?)` | 可选参数,见上文窗口创建参数说明 | Promise\<Window> | 创建并获取一个窗口 |
|
|
636
|
+
| `handle(event, callback)` | `event`: string, `callback`: (data: any) => any | 无 | 监听指定事件 |
|
|
637
|
+
| `unhandle(event, callback)` | `event`: string, `callback`: (data: any) => any | 无 | 取消监听指定事件 |
|
|
638
|
+
| `global` | / | Map\<string, any> | 全局变量 Map |
|
|
639
|
+
| `closeWindow(window)` | `window`: Window | Promise\<void> | 关闭指定窗口并回收至池中 |
|
|
640
|
+
| `onCustomMessage` | `(window: Window, data: string) => void` | 无 | 自定义消息回调函数 |
|
|
597
641
|
|
|
598
642
|
### Window
|
|
599
643
|
|
|
600
|
-
| 方法/属性
|
|
601
|
-
|
|
|
602
|
-
| `loadURL(url)`
|
|
603
|
-
| `loadHTML(html)`
|
|
604
|
-
| `show()`
|
|
605
|
-
| `hide()`
|
|
606
|
-
| `maximize()`
|
|
607
|
-
| `unMaximize()`
|
|
608
|
-
| `minimize()`
|
|
609
|
-
| `unMinimize()`
|
|
610
|
-
| `close()`
|
|
611
|
-
| `setTitle(title)`
|
|
612
|
-
| `setDecorated(isDecorated)`
|
|
613
|
-
| `
|
|
614
|
-
| `
|
|
615
|
-
| `
|
|
616
|
-
| `
|
|
617
|
-
| `
|
|
618
|
-
| `
|
|
619
|
-
| `
|
|
620
|
-
| `
|
|
621
|
-
| `
|
|
622
|
-
| `
|
|
623
|
-
| `
|
|
624
|
-
| `
|
|
625
|
-
| `
|
|
626
|
-
| `
|
|
644
|
+
| 方法/属性 | 参数 | 返回值 | 说明 |
|
|
645
|
+
| --------------------------------------- | ----------------------------------------------------------------- | --------------------------------- | ------------------------------------------------------------- |
|
|
646
|
+
| `loadURL(url)` | `url`: string — 要加载的网页地址 | Promise\<void> | 加载指定 URL |
|
|
647
|
+
| `loadHTML(html)` | `html`: string — HTML 字符串 | Promise\<void> | 加载指定 HTML 内容 |
|
|
648
|
+
| `show()` | 无 | void | 显示窗口 |
|
|
649
|
+
| `hide()` | 无 | void | 隐藏窗口 |
|
|
650
|
+
| `maximize()` | 无 | void | 最大化窗口 |
|
|
651
|
+
| `unMaximize()` | 无 | void | 还原窗口(取消最大化) |
|
|
652
|
+
| `minimize()` | 无 | void | 最小化窗口 |
|
|
653
|
+
| `unMinimize()` | 无 | void | 还原窗口(取消最小化) |
|
|
654
|
+
| `close()` | 无 | void | 关闭窗口并回收至池中 |
|
|
655
|
+
| `setTitle(title)` | `title`: string | void | 设置窗口标题 |
|
|
656
|
+
| `setDecorated(isDecorated)` | `isDecorated`: boolean | void | 设置窗口是否带边框和标题栏 |
|
|
657
|
+
| `setResizable(resizable)` | `resizable`: boolean | void | 设置窗口是否可调整大小 |
|
|
658
|
+
| `setLevel(level)` | `level`: `-1` \| `0` \| `1` | void | 设置窗口层级:-1=置底,0=正常,1=置顶 |
|
|
659
|
+
| `setFullScreen(isFullScreen, options?)` | `isFullScreen`: `boolean`, `options?`: `{ borderless?: boolean }` | void | 设置全屏模式。`borderless: true` 为无边框全屏,否则为独占全屏 |
|
|
660
|
+
| `setIcon(icon)` | `icon`: `Icon` | void | 设置窗口图标 |
|
|
661
|
+
| `setSize(width, height)` | `width`: number, `height`: number | void | 设置窗口尺寸(像素) |
|
|
662
|
+
| `getSize()` | 无 | { width: number, height: number } | 获取窗口尺寸(像素) |
|
|
663
|
+
| `setPosition(x, y)` | `x`: number, `y`: number | void | 设置窗口位置(像素) |
|
|
664
|
+
| `getPosition()` | 无 | { x: number, y: number } | 获取窗口位置(像素) |
|
|
665
|
+
| `focus()` | 无 | void | 窗口获取焦点 |
|
|
666
|
+
| `isFocused()` | 无 | boolean | 是否有焦点 |
|
|
667
|
+
| `isMaximized()` | 无 | boolean | 是否最大化 |
|
|
668
|
+
| `isMinimized()` | 无 | boolean | 是否最小化 |
|
|
669
|
+
| `toggleMaximize()` | 无 | void | 切换最大化状态 |
|
|
670
|
+
| `toggleMinimize()` | 无 | void | 切换最小化状态 |
|
|
671
|
+
| `openDevTools()` | 无 | void | 打开开发者工具 |
|
|
672
|
+
| `closeDevTools()` | 无 | void | 关闭开发者工具 |
|
|
673
|
+
| `id` | 无 | number | 窗口唯一标识,自增编号 |
|
|
627
674
|
|
|
628
675
|
## 开发
|
|
629
676
|
|
package/README.md
CHANGED
|
@@ -41,7 +41,10 @@ import { Application } from "nexfep";
|
|
|
41
41
|
|
|
42
42
|
const app = new Application();
|
|
43
43
|
|
|
44
|
-
const window = await app.windows.createWindow(
|
|
44
|
+
const window = await app.windows.createWindow({
|
|
45
|
+
visible: true,
|
|
46
|
+
decoration: false,
|
|
47
|
+
});
|
|
45
48
|
|
|
46
49
|
await window.loadHTML("<h1 nexfep-area-drag>Hello Nexfep!</h1>");
|
|
47
50
|
```
|
|
@@ -81,11 +84,37 @@ const app = new Application({ LogFilePath: "./app.log" });
|
|
|
81
84
|
- `createLocker(appName)` — Create an application instance lock to prevent multiple instances
|
|
82
85
|
- `exit()` — Exit the application
|
|
83
86
|
|
|
87
|
+
### Icon
|
|
88
|
+
|
|
89
|
+
`Icon` represents an image resource that can be used as a window icon, tray icon, etc.
|
|
90
|
+
|
|
91
|
+
```typescript
|
|
92
|
+
import { Icon } from "nexfep";
|
|
93
|
+
|
|
94
|
+
// Create from file path
|
|
95
|
+
const icon = Icon.from("./icon.png");
|
|
96
|
+
|
|
97
|
+
// Create from Buffer or Uint8Array
|
|
98
|
+
const icon = Icon.from(buffer);
|
|
99
|
+
const icon = Icon.from(uint8Array);
|
|
100
|
+
|
|
101
|
+
// Create from an object containing data/width/height
|
|
102
|
+
const icon = Icon.from({ data: buffer, width: 64, height: 64 });
|
|
103
|
+
const icon = Icon.from({ data: uint8Array, width: 64, height: 64 });
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
**Static Methods**
|
|
107
|
+
|
|
108
|
+
| Method | Parameters | Return Value | Description |
|
|
109
|
+
| ------------------ | ----------------------------------------------------------------------------------------- | ------------ | ------------------------ |
|
|
110
|
+
| `Icon.from(input)` | `string` \| `Buffer` \| `Uint8Array` \| `{ data: Uint8Array \| Buffer, width?, height? }` | `Icon` | Creates an icon instance |
|
|
111
|
+
|
|
84
112
|
### Logger
|
|
85
113
|
|
|
86
114
|
The logger supports both file output and colored console output. It can be accessed via `app.logger`.
|
|
87
115
|
|
|
88
116
|
```typescript
|
|
117
|
+
app.logger.clear();
|
|
89
118
|
app.logger.log("Hello World");
|
|
90
119
|
app.logger.error("An error occurred");
|
|
91
120
|
app.logger.warn("Warning message");
|
|
@@ -95,13 +124,14 @@ app.logger.debug("Debug message");
|
|
|
95
124
|
|
|
96
125
|
**Methods**
|
|
97
126
|
|
|
98
|
-
| Method | Description
|
|
99
|
-
| ---------------- |
|
|
100
|
-
| `
|
|
101
|
-
| `
|
|
102
|
-
| `
|
|
103
|
-
| `
|
|
104
|
-
| `
|
|
127
|
+
| Method | Description |
|
|
128
|
+
| ---------------- | ------------------------------------------------------------------------------ |
|
|
129
|
+
| `clear()` | Clear the log file (only takes effect when the `LogFilePath` parameter is set) |
|
|
130
|
+
| `log(message)` | Log a message |
|
|
131
|
+
| `error(message)` | Log an error message (red) |
|
|
132
|
+
| `warn(message)` | Log a warning message (yellow) |
|
|
133
|
+
| `info(message)` | Log an info message (blue) |
|
|
134
|
+
| `debug(message)` | Log a debug message (gray) |
|
|
105
135
|
|
|
106
136
|
Each method accepts either a string or an array of strings.
|
|
107
137
|
|
|
@@ -143,16 +173,14 @@ locker.unlock();
|
|
|
143
173
|
Create and manage system tray icons with context menus via `app.createTray()`.
|
|
144
174
|
|
|
145
175
|
```typescript
|
|
146
|
-
import {
|
|
176
|
+
import { Icon } from "nexfep";
|
|
177
|
+
|
|
178
|
+
const icon = Icon.from("./icon.png");
|
|
147
179
|
|
|
148
180
|
const tray = app.createTray({
|
|
149
181
|
id: "my-tray",
|
|
150
182
|
tooltip: "My App",
|
|
151
|
-
icon:
|
|
152
|
-
data: readFileSync("./icon.png"),
|
|
153
|
-
width: 32,
|
|
154
|
-
height: 32,
|
|
155
|
-
},
|
|
183
|
+
icon: icon, // Icon instance
|
|
156
184
|
menuItems: [
|
|
157
185
|
{ id: "show", label: "Show Window" },
|
|
158
186
|
{ id: "quit", label: "Quit" },
|
|
@@ -160,29 +188,19 @@ const tray = app.createTray({
|
|
|
160
188
|
});
|
|
161
189
|
```
|
|
162
190
|
|
|
163
|
-
The `icon` field accepts a `TrayIconImage` object:
|
|
164
|
-
|
|
165
|
-
```typescript
|
|
166
|
-
interface TrayIconImage {
|
|
167
|
-
data: Buffer; // Image binary data
|
|
168
|
-
width?: number; // Optional width
|
|
169
|
-
height?: number; // Optional height
|
|
170
|
-
}
|
|
171
|
-
```
|
|
172
|
-
|
|
173
191
|
**Methods**
|
|
174
192
|
|
|
175
|
-
| Method
|
|
176
|
-
|
|
|
177
|
-
| `addMenuItem(item)`
|
|
178
|
-
| `removeMenuItem(id)`
|
|
179
|
-
| `setMenuItems(items)`
|
|
180
|
-
| `setIcon(icon
|
|
181
|
-
| `setTooltip(tooltip)`
|
|
182
|
-
| `on(event, callback)`
|
|
183
|
-
| `show()`
|
|
184
|
-
| `hide()`
|
|
185
|
-
| `destroy()`
|
|
193
|
+
| Method | Description |
|
|
194
|
+
| --------------------- | ------------------------------------------------ |
|
|
195
|
+
| `addMenuItem(item)` | Add a menu item |
|
|
196
|
+
| `removeMenuItem(id)` | Remove a menu item by ID |
|
|
197
|
+
| `setMenuItems(items)` | Replace all menu items |
|
|
198
|
+
| `setIcon(icon)` | Change the tray icon, accepts an `Icon` instance |
|
|
199
|
+
| `setTooltip(tooltip)` | Change the tooltip text |
|
|
200
|
+
| `on(event, callback)` | Listen for tray events (e.g. `'click'`) |
|
|
201
|
+
| `show()` | Show the tray icon |
|
|
202
|
+
| `hide()` | Hide the tray icon |
|
|
203
|
+
| `destroy()` | Destroy the tray icon |
|
|
186
204
|
|
|
187
205
|
```typescript
|
|
188
206
|
tray.on("click", () => {
|
|
@@ -197,13 +215,14 @@ tray.setTooltip("Nexfep App");
|
|
|
197
215
|
Send desktop notifications via `app.utils.notify()`.
|
|
198
216
|
|
|
199
217
|
```typescript
|
|
200
|
-
const notification = app.utils.notify("Title", "Notification body");
|
|
218
|
+
const notification = app.utils.notify("Title", { body: "Notification body" });
|
|
201
219
|
```
|
|
202
220
|
|
|
203
221
|
**Parameters**
|
|
204
222
|
|
|
205
223
|
- `title` — Notification title
|
|
206
|
-
- `
|
|
224
|
+
- `options` (optional) — Configuration object
|
|
225
|
+
- `body` — Notification body text
|
|
207
226
|
|
|
208
227
|
### Window Pool
|
|
209
228
|
|
|
@@ -216,13 +235,38 @@ const pool = app.windows;
|
|
|
216
235
|
### Window Creation
|
|
217
236
|
|
|
218
237
|
```typescript
|
|
219
|
-
|
|
238
|
+
// Use all defaults by omitting parameters
|
|
239
|
+
const win = await pool.createWindow();
|
|
240
|
+
|
|
241
|
+
// Pass partial parameters
|
|
242
|
+
const win = await pool.createWindow({
|
|
243
|
+
visible: true,
|
|
244
|
+
title: "My App",
|
|
245
|
+
});
|
|
246
|
+
|
|
247
|
+
// All parameters
|
|
248
|
+
const win = await pool.createWindow({
|
|
249
|
+
visible: true, // Whether to show immediately, default true
|
|
250
|
+
decoration: true, // Whether to use system decorations, default true
|
|
251
|
+
title: "My App", // Window title, default "Nexfep Window"
|
|
252
|
+
icon: iconInstance, // Window icon, Icon instance, optional
|
|
253
|
+
resizable: true, // Whether the window is resizable, default true
|
|
254
|
+
width: 800, // Window width, default 800
|
|
255
|
+
height: 600, // Window height, default 600
|
|
256
|
+
});
|
|
220
257
|
```
|
|
221
258
|
|
|
222
259
|
**Parameters**
|
|
223
260
|
|
|
224
|
-
|
|
225
|
-
|
|
261
|
+
| Option | Type | Default | Description |
|
|
262
|
+
| ------------ | --------- | ----------------- | ---------------------------------------------------------------------------------------------------------------- |
|
|
263
|
+
| `visible` | `boolean` | `true` | Whether to immediately show the window |
|
|
264
|
+
| `decoration` | `boolean` | `true` | Whether to use system window decorations. When `false`, the window has no border and requires a custom title bar |
|
|
265
|
+
| `title` | `string` | `"Nexfep Window"` | Window title |
|
|
266
|
+
| `icon` | `Icon` | none | Window icon |
|
|
267
|
+
| `resizable` | `boolean` | `true` | Whether the window is resizable |
|
|
268
|
+
| `width` | `number` | `800` | Window width in pixels |
|
|
269
|
+
| `height` | `number` | `600` | Window height in pixels |
|
|
226
270
|
|
|
227
271
|
### Window Operations
|
|
228
272
|
|
|
@@ -584,44 +628,47 @@ Please do not include the outer `metadata` field, just the internal fields. Like
|
|
|
584
628
|
|
|
585
629
|
### WindowPool
|
|
586
630
|
|
|
587
|
-
| Method/Property
|
|
588
|
-
|
|
|
589
|
-
| `createWindow(
|
|
590
|
-
| `handle(event, callback)`
|
|
591
|
-
| `unhandle(event, callback)`
|
|
592
|
-
| `global`
|
|
593
|
-
| `closeWindow(window)`
|
|
594
|
-
| `onCustomMessage`
|
|
631
|
+
| Method/Property | Parameters | Return Value | Description |
|
|
632
|
+
| --------------------------- | ------------------------------------------------------ | ----------------- | ------------------------------------------------------ |
|
|
633
|
+
| `createWindow(options?)` | Optional parameters, see Window Creation section above | Promise\<Window> | Creates and returns a window |
|
|
634
|
+
| `handle(event, callback)` | `event`: string, `callback`: (data: any) => any | None | Listens for the specified event |
|
|
635
|
+
| `unhandle(event, callback)` | `event`: string, `callback`: (data: any) => any | None | Removes the specified event listener |
|
|
636
|
+
| `global` | / | Map\<string, any> | A global variable map |
|
|
637
|
+
| `closeWindow(window)` | `window`: Window | Promise\<void> | Closes the specified window and returns it to the pool |
|
|
638
|
+
| `onCustomMessage` | `(window: Window, data: string) => void` | None | Custom message callback |
|
|
595
639
|
|
|
596
640
|
### Window
|
|
597
641
|
|
|
598
|
-
| Method/Property
|
|
599
|
-
|
|
|
600
|
-
| `loadURL(url)`
|
|
601
|
-
| `loadHTML(html)`
|
|
602
|
-
| `show()`
|
|
603
|
-
| `hide()`
|
|
604
|
-
| `maximize()`
|
|
605
|
-
| `unMaximize()`
|
|
606
|
-
| `minimize()`
|
|
607
|
-
| `unMinimize()`
|
|
608
|
-
| `close()`
|
|
609
|
-
| `setTitle(title)`
|
|
610
|
-
| `setDecorated(isDecorated)`
|
|
611
|
-
| `
|
|
612
|
-
| `
|
|
613
|
-
| `
|
|
614
|
-
| `
|
|
615
|
-
| `
|
|
616
|
-
| `
|
|
617
|
-
| `
|
|
618
|
-
| `
|
|
619
|
-
| `
|
|
620
|
-
| `isFocused()`
|
|
621
|
-
| `
|
|
622
|
-
| `
|
|
623
|
-
| `
|
|
624
|
-
| `
|
|
642
|
+
| Method/Property | Parameters | Return Value | Description |
|
|
643
|
+
| --------------------------------------- | ----------------------------------------------------------------- | --------------------------------- | -------------------------------------------------------------------------------------------------- |
|
|
644
|
+
| `loadURL(url)` | `url`: string — URL to load | Promise\<void> | Loads the specified URL |
|
|
645
|
+
| `loadHTML(html)` | `html`: string — HTML string | Promise\<void> | Loads the specified HTML content |
|
|
646
|
+
| `show()` | None | void | Shows the window |
|
|
647
|
+
| `hide()` | None | void | Hides the window |
|
|
648
|
+
| `maximize()` | None | void | Maximizes the window |
|
|
649
|
+
| `unMaximize()` | None | void | Restores the window (cancels maximize) |
|
|
650
|
+
| `minimize()` | None | void | Minimizes the window |
|
|
651
|
+
| `unMinimize()` | None | void | Restores the window (cancels minimize) |
|
|
652
|
+
| `close()` | None | void | Closes the window and returns to pool |
|
|
653
|
+
| `setTitle(title)` | `title`: string | void | Sets the window title |
|
|
654
|
+
| `setDecorated(isDecorated)` | `isDecorated`: boolean | void | Sets whether the window has borders and title bar |
|
|
655
|
+
| `setResizable(resizable)` | `resizable`: boolean | void | Sets whether the window is resizable |
|
|
656
|
+
| `setLevel(level)` | `level`: `-1` \| `0` \| `1` | void | Sets window level: -1=bottom, 0=normal, 1=top |
|
|
657
|
+
| `setFullScreen(isFullScreen, options?)` | `isFullScreen`: `boolean`, `options?`: `{ borderless?: boolean }` | void | Sets fullscreen mode. `borderless: true` for borderless fullscreen, otherwise exclusive fullscreen |
|
|
658
|
+
| `setIcon(icon)` | `icon`: `Icon` | void | Sets the window icon |
|
|
659
|
+
| `setSize(width, height)` | `width`: number, `height`: number | void | Sets the window size in pixels |
|
|
660
|
+
| `getSize()` | None | { width: number, height: number } | Gets the window size in pixels |
|
|
661
|
+
| `setPosition(x, y)` | `x`: number, `y`: number | void | Sets the window position in pixels |
|
|
662
|
+
| `getPosition()` | None | { x: number, y: number } | Gets the window position in pixels |
|
|
663
|
+
| `focus()` | None | void | Focuses the window |
|
|
664
|
+
| `isFocused()` | None | boolean | Whether the window has focus |
|
|
665
|
+
| `isMaximized()` | None | boolean | Whether the window is maximized |
|
|
666
|
+
| `isMinimized()` | None | boolean | Whether the window is minimized |
|
|
667
|
+
| `toggleMaximize()` | None | void | Toggles the window maximized state |
|
|
668
|
+
| `toggleMinimize()` | None | void | Toggles the window minimized state |
|
|
669
|
+
| `openDevTools()` | None | void | Opens developer tools |
|
|
670
|
+
| `closeDevTools()` | None | void | Closes developer tools |
|
|
671
|
+
| `id` | None | number | Unique window identifier, auto-incrementing |
|
|
625
672
|
|
|
626
673
|
## Development
|
|
627
674
|
|
package/frontend/index.d.ts
CHANGED
|
@@ -1,23 +1,23 @@
|
|
|
1
|
-
export {}
|
|
1
|
+
export {};
|
|
2
2
|
|
|
3
3
|
declare global {
|
|
4
4
|
interface Window {
|
|
5
|
-
tell: (to: number, message: string, data?: any) => void
|
|
6
|
-
broadcast: (message: string, data?: any) => void
|
|
7
|
-
invoke: (event: string, data?: any) => Promise<any
|
|
8
|
-
close: () => void
|
|
9
|
-
minimize: () => void
|
|
10
|
-
unminimize: () => void
|
|
11
|
-
toggleMaximize: () => void
|
|
12
|
-
toggleMinimize: () => void
|
|
13
|
-
maximize: () => void
|
|
14
|
-
unmaximize: () => void
|
|
15
|
-
setTitle: (title: string) => void
|
|
16
|
-
openDevTools: () => void
|
|
17
|
-
closeDevTools: () => void
|
|
18
|
-
setGlobal: (name: string, value: any) => void
|
|
19
|
-
getGlobal: (name: string) => Promise<any
|
|
20
|
-
id: number
|
|
21
|
-
isNexfepLoadDone: boolean
|
|
5
|
+
tell: (to: number, message: string, data?: any) => void;
|
|
6
|
+
broadcast: (message: string, data?: any) => void;
|
|
7
|
+
invoke: (event: string, data?: any) => Promise<any>;
|
|
8
|
+
close: () => void;
|
|
9
|
+
minimize: () => void;
|
|
10
|
+
unminimize: () => void;
|
|
11
|
+
toggleMaximize: () => void;
|
|
12
|
+
toggleMinimize: () => void;
|
|
13
|
+
maximize: () => void;
|
|
14
|
+
unmaximize: () => void;
|
|
15
|
+
setTitle: (title: string) => void;
|
|
16
|
+
openDevTools: () => void;
|
|
17
|
+
closeDevTools: () => void;
|
|
18
|
+
setGlobal: (name: string, value: any) => void;
|
|
19
|
+
getGlobal: (name: string) => Promise<any>;
|
|
20
|
+
id: number;
|
|
21
|
+
isNexfepLoadDone: boolean;
|
|
22
22
|
}
|
|
23
|
-
}
|
|
23
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "nexfep",
|
|
3
|
-
"version": "0.
|
|
3
|
+
"version": "0.6.0",
|
|
4
4
|
"description": "A desktop application framework based on @webviewjs/webview",
|
|
5
5
|
"keywords": [
|
|
6
6
|
"@webviewjs/webview",
|
|
@@ -20,12 +20,6 @@
|
|
|
20
20
|
"bin": {
|
|
21
21
|
"nexfep": "cli/index.mjs"
|
|
22
22
|
},
|
|
23
|
-
"typesVersions": {
|
|
24
|
-
"*": {
|
|
25
|
-
".": ["./index.d.ts"],
|
|
26
|
-
"frontend": ["./frontend/index.d.ts"]
|
|
27
|
-
}
|
|
28
|
-
},
|
|
29
23
|
"files": [
|
|
30
24
|
"index.js",
|
|
31
25
|
"index.d.ts",
|
|
@@ -47,10 +41,22 @@
|
|
|
47
41
|
"src/Logger.d.ts",
|
|
48
42
|
"src/SingleInstance.js",
|
|
49
43
|
"src/SingleInstance.d.ts",
|
|
44
|
+
"src/Icon.js",
|
|
45
|
+
"src/Icon.d.ts",
|
|
50
46
|
"frontend/index.d.ts"
|
|
51
47
|
],
|
|
52
48
|
"type": "module",
|
|
53
49
|
"main": "./index.js",
|
|
50
|
+
"typesVersions": {
|
|
51
|
+
"*": {
|
|
52
|
+
".": [
|
|
53
|
+
"./index.d.ts"
|
|
54
|
+
],
|
|
55
|
+
"frontend": [
|
|
56
|
+
"./frontend/index.d.ts"
|
|
57
|
+
]
|
|
58
|
+
}
|
|
59
|
+
},
|
|
54
60
|
"scripts": {
|
|
55
61
|
"compile": "tsc",
|
|
56
62
|
"fmt": "oxfmt --check",
|
|
@@ -60,7 +66,7 @@
|
|
|
60
66
|
},
|
|
61
67
|
"dependencies": {
|
|
62
68
|
"@nexfteam/single-instance": "^0.0.7",
|
|
63
|
-
"@webviewjs/webview": "0.4.
|
|
69
|
+
"@webviewjs/webview": "0.4.1"
|
|
64
70
|
},
|
|
65
71
|
"devDependencies": {
|
|
66
72
|
"@types/node": "^22.0.0",
|
package/src/Application.d.ts
CHANGED
|
@@ -1,12 +1,15 @@
|
|
|
1
|
-
import { Application as WebviewApplication,
|
|
1
|
+
import { Application as WebviewApplication, Notification } from "@webviewjs/webview";
|
|
2
2
|
import { WindowPool } from "./WindowManager.js";
|
|
3
3
|
import { Tray } from "./Tray.js";
|
|
4
4
|
import { Logger } from "./Logger.js";
|
|
5
5
|
import { Locker } from "./SingleInstance.js";
|
|
6
|
+
import { Icon } from "./Icon.js";
|
|
6
7
|
declare class __Utils {
|
|
7
8
|
app: WebviewApplication;
|
|
8
9
|
constructor(app: WebviewApplication);
|
|
9
|
-
notify(title: string,
|
|
10
|
+
notify(title: string, options?: {
|
|
11
|
+
body?: string;
|
|
12
|
+
}): Notification;
|
|
10
13
|
}
|
|
11
14
|
declare class Application {
|
|
12
15
|
app: WebviewApplication;
|
|
@@ -20,7 +23,7 @@ declare class Application {
|
|
|
20
23
|
createTray(options: {
|
|
21
24
|
id: string;
|
|
22
25
|
tooltip: string;
|
|
23
|
-
icon
|
|
26
|
+
icon?: Icon;
|
|
24
27
|
menuItems: Array<{
|
|
25
28
|
id: string;
|
|
26
29
|
label: string;
|
|
@@ -29,4 +32,4 @@ declare class Application {
|
|
|
29
32
|
createLocker(appName: string): Locker;
|
|
30
33
|
exit(): void;
|
|
31
34
|
}
|
|
32
|
-
export { Application };
|
|
35
|
+
export { Application, Icon };
|
package/src/Application.js
CHANGED
|
@@ -3,13 +3,14 @@ import { WindowPool } from "./WindowManager.js";
|
|
|
3
3
|
import { Tray } from "./Tray.js";
|
|
4
4
|
import { Logger } from "./Logger.js";
|
|
5
5
|
import { Locker } from "./SingleInstance.js";
|
|
6
|
+
import { Icon } from "./Icon.js";
|
|
6
7
|
class __Utils {
|
|
7
8
|
app;
|
|
8
9
|
constructor(app) {
|
|
9
10
|
this.app = app;
|
|
10
11
|
}
|
|
11
|
-
notify(title,
|
|
12
|
-
const notification = new Notification(title, { body });
|
|
12
|
+
notify(title, options) {
|
|
13
|
+
const notification = new Notification(title, { body: options?.body });
|
|
13
14
|
return notification;
|
|
14
15
|
}
|
|
15
16
|
}
|
|
@@ -39,4 +40,4 @@ class Application {
|
|
|
39
40
|
this.app.exit();
|
|
40
41
|
}
|
|
41
42
|
}
|
|
42
|
-
export { Application };
|
|
43
|
+
export { Application, Icon };
|
package/src/Icon.d.ts
ADDED
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { TrayIconImage } from "@webviewjs/webview";
|
|
2
|
+
declare class Icon {
|
|
3
|
+
data: Uint8Array;
|
|
4
|
+
width?: number;
|
|
5
|
+
height?: number;
|
|
6
|
+
constructor(data: Uint8Array, width?: number, height?: number);
|
|
7
|
+
static from(input: string | Buffer | Uint8Array | {
|
|
8
|
+
data: Uint8Array;
|
|
9
|
+
width?: number;
|
|
10
|
+
height?: number;
|
|
11
|
+
} | {
|
|
12
|
+
data: Buffer;
|
|
13
|
+
width?: number;
|
|
14
|
+
height?: number;
|
|
15
|
+
}): Icon;
|
|
16
|
+
toTrayIconImage(): TrayIconImage;
|
|
17
|
+
toBuffer(): Buffer;
|
|
18
|
+
}
|
|
19
|
+
export { Icon };
|
package/src/Icon.js
ADDED
|
@@ -0,0 +1,36 @@
|
|
|
1
|
+
import fs from "fs";
|
|
2
|
+
class Icon {
|
|
3
|
+
data;
|
|
4
|
+
width;
|
|
5
|
+
height;
|
|
6
|
+
constructor(data, width, height) {
|
|
7
|
+
this.data = data;
|
|
8
|
+
this.width = width;
|
|
9
|
+
this.height = height;
|
|
10
|
+
}
|
|
11
|
+
static from(input) {
|
|
12
|
+
if (typeof input === "string") {
|
|
13
|
+
return new Icon(new Uint8Array(fs.readFileSync(input)));
|
|
14
|
+
}
|
|
15
|
+
else if (input instanceof Uint8Array) {
|
|
16
|
+
return new Icon(input);
|
|
17
|
+
}
|
|
18
|
+
else if (input instanceof Buffer) {
|
|
19
|
+
return new Icon(new Uint8Array(input));
|
|
20
|
+
}
|
|
21
|
+
else if (typeof input === "object" && input.data instanceof Uint8Array) {
|
|
22
|
+
return new Icon(input.data, input.width, input.height);
|
|
23
|
+
}
|
|
24
|
+
else if (typeof input === "object" && input.data instanceof Buffer) {
|
|
25
|
+
return new Icon(new Uint8Array(input.data), input.width, input.height);
|
|
26
|
+
}
|
|
27
|
+
throw new Error("Unsupported input type");
|
|
28
|
+
}
|
|
29
|
+
toTrayIconImage() {
|
|
30
|
+
return { data: Buffer.from(this.data), width: this.width, height: this.height };
|
|
31
|
+
}
|
|
32
|
+
toBuffer() {
|
|
33
|
+
return Buffer.from(this.data);
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
export { Icon };
|
package/src/Logger.d.ts
CHANGED
package/src/Logger.js
CHANGED
|
@@ -16,7 +16,6 @@ class Logger {
|
|
|
16
16
|
let styleArgIndex = 1;
|
|
17
17
|
let result = "";
|
|
18
18
|
let currentAnsiStyle = "";
|
|
19
|
-
// 命名前景色映射
|
|
20
19
|
const fgColors = {
|
|
21
20
|
black: "\x1b[30m",
|
|
22
21
|
red: "\x1b[31m",
|
|
@@ -36,7 +35,6 @@ class Logger {
|
|
|
36
35
|
lightcyan: "\x1b[96m",
|
|
37
36
|
lightwhite: "\x1b[97m",
|
|
38
37
|
};
|
|
39
|
-
// 命名背景色映射
|
|
40
38
|
const bgColors = {
|
|
41
39
|
black: "\x1b[40m",
|
|
42
40
|
red: "\x1b[41m",
|
|
@@ -47,7 +45,6 @@ class Logger {
|
|
|
47
45
|
cyan: "\x1b[46m",
|
|
48
46
|
white: "\x1b[47m",
|
|
49
47
|
};
|
|
50
|
-
// 文字样式:加粗、斜体、下划线
|
|
51
48
|
const textStyles = {
|
|
52
49
|
bold: "\x1b[1m",
|
|
53
50
|
"font-weight:bold": "\x1b[1m",
|
|
@@ -57,14 +54,11 @@ class Logger {
|
|
|
57
54
|
"text-decoration:underline": "\x1b[4m",
|
|
58
55
|
none: RESET,
|
|
59
56
|
};
|
|
60
|
-
/** hex/rgb 转 ANSI 24位真彩色 */
|
|
61
57
|
function colorToAnsi(colorVal, isBg = false) {
|
|
62
58
|
let val = colorVal.trim().toLowerCase();
|
|
63
|
-
// 命名色
|
|
64
59
|
const colorMap = isBg ? bgColors : fgColors;
|
|
65
60
|
if (colorMap[val])
|
|
66
61
|
return colorMap[val];
|
|
67
|
-
// hex #fff #ffffff
|
|
68
62
|
const hexReg = /^#([0-9a-f]{3}|[0-9a-f]{6})$/;
|
|
69
63
|
if (hexReg.test(val)) {
|
|
70
64
|
let hex = val.replace("#", "");
|
|
@@ -78,7 +72,6 @@ class Logger {
|
|
|
78
72
|
const b = parseInt(hex.slice(4, 6), 16);
|
|
79
73
|
return isBg ? `\x1b[48;2;${r};${g};${b}m` : `\x1b[38;2;${r};${g};${b}m`;
|
|
80
74
|
}
|
|
81
|
-
// rgb(r,g,b)
|
|
82
75
|
const rgbReg = /rgb\(\s*(\d+)\s*,\s*(\d+)\s*,\s*(\d+)\s*\)/;
|
|
83
76
|
const rgbMatch = val.match(rgbReg);
|
|
84
77
|
if (rgbMatch) {
|
|
@@ -87,7 +80,6 @@ class Logger {
|
|
|
87
80
|
}
|
|
88
81
|
return "";
|
|
89
82
|
}
|
|
90
|
-
/** 解析CSS样式字符串为ANSI序列 */
|
|
91
83
|
function parseColorStyle(styleStr) {
|
|
92
84
|
if (!styleStr)
|
|
93
85
|
return RESET;
|
|
@@ -100,17 +92,14 @@ class Logger {
|
|
|
100
92
|
const [prop, ...rest] = rule.split(":");
|
|
101
93
|
const propKey = prop.trim().toLowerCase();
|
|
102
94
|
const value = rest.join(":").trim().toLowerCase();
|
|
103
|
-
// 文字样式
|
|
104
95
|
if (textStyles[`${propKey}:${value}`] || textStyles[value]) {
|
|
105
96
|
ansi += textStyles[`${propKey}:${value}`] ?? textStyles[value];
|
|
106
97
|
continue;
|
|
107
98
|
}
|
|
108
|
-
// 前景色
|
|
109
99
|
if (propKey === "color") {
|
|
110
100
|
ansi += colorToAnsi(value, false);
|
|
111
101
|
continue;
|
|
112
102
|
}
|
|
113
|
-
// 背景色
|
|
114
103
|
if (propKey === "background" || propKey === "background-color") {
|
|
115
104
|
ansi += colorToAnsi(value, true);
|
|
116
105
|
continue;
|
|
@@ -120,7 +109,6 @@ class Logger {
|
|
|
120
109
|
}
|
|
121
110
|
for (const segment of parts) {
|
|
122
111
|
if (segment === "%c") {
|
|
123
|
-
// 取出下一个样式参数,参数不足则重置样式
|
|
124
112
|
const styleStr = args[styleArgIndex];
|
|
125
113
|
styleArgIndex++;
|
|
126
114
|
currentAnsiStyle = parseColorStyle(String(styleStr ?? ""));
|
|
@@ -136,10 +124,8 @@ class Logger {
|
|
|
136
124
|
}
|
|
137
125
|
}
|
|
138
126
|
}
|
|
139
|
-
// 全局末尾统一重置,防止后续日志被染色
|
|
140
127
|
if (currentAnsiStyle)
|
|
141
128
|
result += RESET;
|
|
142
|
-
// 剩余非样式参数直接拼接
|
|
143
129
|
const extraArgs = args.slice(styleArgIndex);
|
|
144
130
|
if (extraArgs.length) {
|
|
145
131
|
result += " " + extraArgs.map(String).join(" ");
|
|
@@ -192,5 +178,10 @@ class Logger {
|
|
|
192
178
|
this.__printLog(0, "Debug", [args], "\x1b[90m", "\x1b[0m");
|
|
193
179
|
}
|
|
194
180
|
}
|
|
181
|
+
clear() {
|
|
182
|
+
if (this.logFilePath) {
|
|
183
|
+
fs.writeFileSync(this.logFilePath, "");
|
|
184
|
+
}
|
|
185
|
+
}
|
|
195
186
|
}
|
|
196
187
|
export { Logger };
|
package/src/Tray.d.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
|
-
import { Application, TrayIcon
|
|
1
|
+
import { Application, TrayIcon } from "@webviewjs/webview";
|
|
2
|
+
import { Icon } from "./Icon.js";
|
|
2
3
|
declare class Tray {
|
|
3
4
|
app: Application;
|
|
4
5
|
tray: TrayIcon;
|
|
@@ -10,7 +11,7 @@ declare class Tray {
|
|
|
10
11
|
constructor(app: Application, options: {
|
|
11
12
|
id: string;
|
|
12
13
|
tooltip: string;
|
|
13
|
-
icon
|
|
14
|
+
icon?: Icon;
|
|
14
15
|
menuItems: Array<{
|
|
15
16
|
id: string;
|
|
16
17
|
label: string;
|
|
@@ -26,7 +27,7 @@ declare class Tray {
|
|
|
26
27
|
id: string;
|
|
27
28
|
label: string;
|
|
28
29
|
}>): void;
|
|
29
|
-
setIcon(icon:
|
|
30
|
+
setIcon(icon: Icon): void;
|
|
30
31
|
on(event: string, callback: (event: any) => void): void;
|
|
31
32
|
setTooltip(tooltip: string): void;
|
|
32
33
|
hide(): void;
|
package/src/Tray.js
CHANGED
|
@@ -10,7 +10,7 @@ class Tray {
|
|
|
10
10
|
this.tray = app.createTrayIcon({
|
|
11
11
|
id: options.id,
|
|
12
12
|
tooltip: options.tooltip,
|
|
13
|
-
icon: options.icon,
|
|
13
|
+
icon: options.icon?.toTrayIconImage(),
|
|
14
14
|
menu: {
|
|
15
15
|
items: this.menuItems,
|
|
16
16
|
},
|
|
@@ -36,9 +36,9 @@ class Tray {
|
|
|
36
36
|
this.menuItems = items;
|
|
37
37
|
this.tray.setMenu({ items: this.menuItems });
|
|
38
38
|
}
|
|
39
|
-
setIcon(icon
|
|
39
|
+
setIcon(icon) {
|
|
40
40
|
this.__ErrorWhenDestroyed();
|
|
41
|
-
this.tray.setIcon(icon, width, height);
|
|
41
|
+
this.tray.setIcon(icon.data, icon.width, icon.height);
|
|
42
42
|
}
|
|
43
43
|
on(event, callback) {
|
|
44
44
|
this.__ErrorWhenDestroyed();
|
package/src/WindowManager.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import { Application, BrowserWindow, Webview } from "@webviewjs/webview";
|
|
2
2
|
import { Logger } from "./Logger.js";
|
|
3
|
+
import { Icon } from "./Icon.js";
|
|
3
4
|
declare class Window {
|
|
4
5
|
window: BrowserWindow;
|
|
5
6
|
webview: Webview;
|
|
@@ -9,9 +10,13 @@ declare class Window {
|
|
|
9
10
|
id: number;
|
|
10
11
|
private myPool;
|
|
11
12
|
constructor(window: BrowserWindow, webview: Webview, id: number, myPool: WindowPool);
|
|
13
|
+
setLevel(level: -1 | 0 | 1): void;
|
|
14
|
+
setFullScreen(isFullScreen: boolean, options?: {
|
|
15
|
+
borderless?: boolean;
|
|
16
|
+
}): void;
|
|
12
17
|
setDecorated(isDecorated: boolean): void;
|
|
13
18
|
setTitle(title: string): void;
|
|
14
|
-
|
|
19
|
+
setResizable(resizable: boolean): void;
|
|
15
20
|
maximize(): void;
|
|
16
21
|
minimize(): void;
|
|
17
22
|
unMaximize(): void;
|
|
@@ -22,6 +27,7 @@ declare class Window {
|
|
|
22
27
|
toggleMinimize(): void;
|
|
23
28
|
openDevTools(): void;
|
|
24
29
|
closeDevTools(): void;
|
|
30
|
+
setIcon(icon: Icon): void;
|
|
25
31
|
setSize(width: number, height: number): void;
|
|
26
32
|
getSize(): import("@webviewjs/webview").Dimensions;
|
|
27
33
|
setPosition(x: number, y: number): void;
|
|
@@ -51,7 +57,15 @@ declare class WindowPool {
|
|
|
51
57
|
__injectCode(window: Window, code: string): Promise<void>;
|
|
52
58
|
__injectControlFunctions(windowObj: Window): Promise<void>;
|
|
53
59
|
__createNewWindowObj(): Promise<Window>;
|
|
54
|
-
createWindow(
|
|
60
|
+
createWindow(options?: {
|
|
61
|
+
visible?: boolean;
|
|
62
|
+
decoration?: boolean;
|
|
63
|
+
title?: string;
|
|
64
|
+
icon?: Icon;
|
|
65
|
+
resizable?: boolean;
|
|
66
|
+
width?: number;
|
|
67
|
+
height?: number;
|
|
68
|
+
}): Promise<Window>;
|
|
55
69
|
closeWindow(window: Window): Promise<void>;
|
|
56
70
|
handle(event: string, callback: (data: any) => any): Promise<void>;
|
|
57
71
|
unhandle(event: string, callback: (data: any) => any): Promise<void>;
|
package/src/WindowManager.js
CHANGED
|
@@ -19,6 +19,36 @@ class Window {
|
|
|
19
19
|
this.isDecorated = false;
|
|
20
20
|
this.id = id;
|
|
21
21
|
}
|
|
22
|
+
setLevel(level) {
|
|
23
|
+
if (level == -1) {
|
|
24
|
+
this.window.setAlwaysOnTop(false);
|
|
25
|
+
this.window.setAlwaysOnBottom(true);
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
else if (level == 0) {
|
|
29
|
+
this.window.setAlwaysOnTop(false);
|
|
30
|
+
this.window.setAlwaysOnBottom(false);
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
else if (level == 1) {
|
|
34
|
+
this.window.setAlwaysOnTop(true);
|
|
35
|
+
this.window.setAlwaysOnBottom(false);
|
|
36
|
+
return;
|
|
37
|
+
}
|
|
38
|
+
}
|
|
39
|
+
setFullScreen(isFullScreen, options) {
|
|
40
|
+
if (isFullScreen) {
|
|
41
|
+
if (options?.borderless) {
|
|
42
|
+
this.window.setFullscreen(1);
|
|
43
|
+
}
|
|
44
|
+
else {
|
|
45
|
+
this.window.setFullscreen(0);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
else {
|
|
49
|
+
this.window.setFullscreen(null);
|
|
50
|
+
}
|
|
51
|
+
}
|
|
22
52
|
setDecorated(isDecorated) {
|
|
23
53
|
this.window.setDecorations(isDecorated);
|
|
24
54
|
this.isDecorated = isDecorated;
|
|
@@ -26,7 +56,7 @@ class Window {
|
|
|
26
56
|
setTitle(title) {
|
|
27
57
|
this.window.setTitle(title);
|
|
28
58
|
}
|
|
29
|
-
|
|
59
|
+
setResizable(resizable) {
|
|
30
60
|
this.window.setResizable(resizable);
|
|
31
61
|
}
|
|
32
62
|
maximize() {
|
|
@@ -69,6 +99,9 @@ class Window {
|
|
|
69
99
|
closeDevTools() {
|
|
70
100
|
this.webview.closeDevtools();
|
|
71
101
|
}
|
|
102
|
+
setIcon(icon) {
|
|
103
|
+
this.window.setWindowIcon(icon.data, icon.width, icon.height);
|
|
104
|
+
}
|
|
72
105
|
setSize(width, height) {
|
|
73
106
|
this.window.setSize(width, height);
|
|
74
107
|
}
|
|
@@ -325,7 +358,7 @@ class WindowPool {
|
|
|
325
358
|
return await new Promise((resolve) => {
|
|
326
359
|
setImmediate(() => {
|
|
327
360
|
const window = this.app.createBrowserWindow({
|
|
328
|
-
title: "Nexfep",
|
|
361
|
+
title: "Nexfep Window",
|
|
329
362
|
visible: false,
|
|
330
363
|
focused: false,
|
|
331
364
|
});
|
|
@@ -444,16 +477,22 @@ class WindowPool {
|
|
|
444
477
|
});
|
|
445
478
|
});
|
|
446
479
|
}
|
|
447
|
-
async createWindow(
|
|
480
|
+
async createWindow(options) {
|
|
448
481
|
const window = this.windows.find((w) => w.isOpen === false) || (await this.__createNewWindowObj());
|
|
449
482
|
this.freeWindowCount--;
|
|
450
483
|
if (window) {
|
|
451
484
|
window.isOpen = true;
|
|
452
|
-
window.isShow =
|
|
453
|
-
window.setDecorated(
|
|
454
|
-
if (
|
|
485
|
+
window.isShow = options?.visible ?? true;
|
|
486
|
+
window.setDecorated(options?.decoration ?? true);
|
|
487
|
+
if (options?.visible ?? true) {
|
|
455
488
|
window.show();
|
|
456
489
|
}
|
|
490
|
+
window.setTitle(options?.title ?? "Nexfep Window");
|
|
491
|
+
if (options?.icon) {
|
|
492
|
+
window.setIcon(options?.icon);
|
|
493
|
+
}
|
|
494
|
+
window.setResizable(options?.resizable ?? true);
|
|
495
|
+
window.setSize(options?.width ?? 800, options?.height ?? 600);
|
|
457
496
|
}
|
|
458
497
|
if (this.freeWindowCount == 0) {
|
|
459
498
|
this.__createNewWindowObj();
|