electrobun 0.4.1 → 0.6.0-beta.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/{templates/multitab-browser/bun.lock → bun.lock} +20 -13
- package/dist/api/bun/proc/native.ts +84 -16
- package/package.json +14 -16
- package/BETA_RELEASE.md +0 -67
- package/BUILD.md +0 -90
- package/LICENSE +0 -21
- package/README.md +0 -102
- package/debug.js +0 -5
- package/templates/hello-world/README.md +0 -57
- package/templates/hello-world/bun.lock +0 -225
- package/templates/hello-world/electrobun.config.ts +0 -28
- package/templates/hello-world/package.json +0 -16
- package/templates/hello-world/src/bun/index.ts +0 -15
- package/templates/hello-world/src/mainview/index.css +0 -124
- package/templates/hello-world/src/mainview/index.html +0 -46
- package/templates/hello-world/src/mainview/index.ts +0 -1
- package/templates/interactive-playground/README.md +0 -26
- package/templates/interactive-playground/assets/tray-icon.png +0 -0
- package/templates/interactive-playground/electrobun.config.ts +0 -36
- package/templates/interactive-playground/package-lock.json +0 -1112
- package/templates/interactive-playground/package.json +0 -15
- package/templates/interactive-playground/src/bun/demos/files.ts +0 -70
- package/templates/interactive-playground/src/bun/demos/menus.ts +0 -139
- package/templates/interactive-playground/src/bun/demos/rpc.ts +0 -83
- package/templates/interactive-playground/src/bun/demos/system.ts +0 -72
- package/templates/interactive-playground/src/bun/demos/updates.ts +0 -105
- package/templates/interactive-playground/src/bun/demos/windows.ts +0 -90
- package/templates/interactive-playground/src/bun/index.ts +0 -124
- package/templates/interactive-playground/src/bun/types/rpc.ts +0 -109
- package/templates/interactive-playground/src/mainview/components/EventLog.ts +0 -107
- package/templates/interactive-playground/src/mainview/components/Sidebar.ts +0 -65
- package/templates/interactive-playground/src/mainview/components/Toast.ts +0 -57
- package/templates/interactive-playground/src/mainview/demos/FileDemo.ts +0 -211
- package/templates/interactive-playground/src/mainview/demos/MenuDemo.ts +0 -102
- package/templates/interactive-playground/src/mainview/demos/RPCDemo.ts +0 -229
- package/templates/interactive-playground/src/mainview/demos/TrayDemo.ts +0 -132
- package/templates/interactive-playground/src/mainview/demos/WebViewDemo.ts +0 -465
- package/templates/interactive-playground/src/mainview/demos/WindowDemo.ts +0 -207
- package/templates/interactive-playground/src/mainview/index.css +0 -538
- package/templates/interactive-playground/src/mainview/index.html +0 -103
- package/templates/interactive-playground/src/mainview/index.ts +0 -238
- package/templates/multitab-browser/README.md +0 -34
- package/templates/multitab-browser/electrobun.config.ts +0 -32
- package/templates/multitab-browser/package-lock.json +0 -20
- package/templates/multitab-browser/package.json +0 -12
- package/templates/multitab-browser/src/bun/index.ts +0 -144
- package/templates/multitab-browser/src/bun/tabManager.ts +0 -200
- package/templates/multitab-browser/src/bun/types/rpc.ts +0 -78
- package/templates/multitab-browser/src/mainview/index.css +0 -487
- package/templates/multitab-browser/src/mainview/index.html +0 -94
- package/templates/multitab-browser/src/mainview/index.ts +0 -634
- package/templates/photo-booth/README.md +0 -108
- package/templates/photo-booth/bun.lock +0 -239
- package/templates/photo-booth/electrobun.config.ts +0 -32
- package/templates/photo-booth/package.json +0 -17
- package/templates/photo-booth/src/bun/index.ts +0 -92
- package/templates/photo-booth/src/mainview/index.css +0 -465
- package/templates/photo-booth/src/mainview/index.html +0 -124
- package/templates/photo-booth/src/mainview/index.ts +0 -499
- package/test-new-window-events.ts +0 -26
- package/test-new-window.html +0 -75
- package/test-npm-install.sh +0 -34
- package/tests/bun.lock +0 -14
- package/tests/electrobun.config.ts +0 -45
- package/tests/package-lock.json +0 -36
- package/tests/package.json +0 -13
- package/tests/src/bun/index.ts +0 -100
- package/tests/src/bun/test-runner.ts +0 -508
- package/tests/src/mainview/index.html +0 -110
- package/tests/src/mainview/index.ts +0 -458
- package/tests/src/mainview/styles/main.css +0 -451
- package/tests/src/testviews/tray-test.html +0 -57
- package/tests/src/testviews/webview-mask.html +0 -114
- package/tests/src/testviews/webview-navigation.html +0 -36
- package/tests/src/testviews/window-create.html +0 -17
- package/tests/src/testviews/window-events.html +0 -29
- package/tests/src/testviews/window-focus.html +0 -37
- package/tests/src/webviewtag/index.ts +0 -11
|
@@ -1,15 +0,0 @@
|
|
|
1
|
-
{
|
|
2
|
-
"name": "electrobun-interactive-playground",
|
|
3
|
-
"version": "0.0.1",
|
|
4
|
-
"description": "Interactive playground for exploring Electrobun features",
|
|
5
|
-
"type": "module",
|
|
6
|
-
"scripts": {
|
|
7
|
-
"build:dev": "electrobun build",
|
|
8
|
-
"build:canary": "electrobun build --canary",
|
|
9
|
-
"start": "electrobun build && electrobun dev",
|
|
10
|
-
"start:canary": "electrobun build --canary && electrobun dev --canary"
|
|
11
|
-
},
|
|
12
|
-
"dependencies": {
|
|
13
|
-
"electrobun": "latest"
|
|
14
|
-
}
|
|
15
|
-
}
|
|
@@ -1,70 +0,0 @@
|
|
|
1
|
-
import { Utils } from "electrobun/bun";
|
|
2
|
-
import { join } from "path";
|
|
3
|
-
import { homedir } from "os";
|
|
4
|
-
|
|
5
|
-
class FileManager {
|
|
6
|
-
async openFileDialog(options: {
|
|
7
|
-
multiple?: boolean;
|
|
8
|
-
fileTypes?: string[];
|
|
9
|
-
startingFolder?: string;
|
|
10
|
-
}) {
|
|
11
|
-
try {
|
|
12
|
-
const result = await Utils.openFileDialog({
|
|
13
|
-
startingFolder: options.startingFolder || join(homedir(), "Desktop"),
|
|
14
|
-
allowedFileTypes: options.fileTypes?.join(",") || "*",
|
|
15
|
-
canChooseFiles: true,
|
|
16
|
-
canChooseDirectory: false,
|
|
17
|
-
allowsMultipleSelection: options.multiple || false,
|
|
18
|
-
});
|
|
19
|
-
|
|
20
|
-
// Filter out empty strings
|
|
21
|
-
const filteredResult = result.filter(path => path.trim() !== "");
|
|
22
|
-
this.onFileSelected?.(filteredResult);
|
|
23
|
-
|
|
24
|
-
return filteredResult;
|
|
25
|
-
} catch (error) {
|
|
26
|
-
console.error("File dialog error:", error);
|
|
27
|
-
return [];
|
|
28
|
-
}
|
|
29
|
-
}
|
|
30
|
-
|
|
31
|
-
async moveToTrash(path: string) {
|
|
32
|
-
try {
|
|
33
|
-
await Utils.moveToTrash(path);
|
|
34
|
-
this.onSystemEvent?.({
|
|
35
|
-
type: 'file-trashed',
|
|
36
|
-
details: { path, success: true }
|
|
37
|
-
});
|
|
38
|
-
} catch (error) {
|
|
39
|
-
console.error("Move to trash error:", error);
|
|
40
|
-
this.onSystemEvent?.({
|
|
41
|
-
type: 'file-trashed',
|
|
42
|
-
details: { path, success: false, error: error.message }
|
|
43
|
-
});
|
|
44
|
-
throw error;
|
|
45
|
-
}
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
async showInFinder(path: string) {
|
|
49
|
-
try {
|
|
50
|
-
await Utils.showItemInFolder(path);
|
|
51
|
-
this.onSystemEvent?.({
|
|
52
|
-
type: 'show-in-finder',
|
|
53
|
-
details: { path, success: true }
|
|
54
|
-
});
|
|
55
|
-
} catch (error) {
|
|
56
|
-
console.error("Show in finder error:", error);
|
|
57
|
-
this.onSystemEvent?.({
|
|
58
|
-
type: 'show-in-finder',
|
|
59
|
-
details: { path, success: false, error: error.message }
|
|
60
|
-
});
|
|
61
|
-
throw error;
|
|
62
|
-
}
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
// Event callbacks
|
|
66
|
-
onFileSelected?: (paths: string[]) => void;
|
|
67
|
-
onSystemEvent?: (event: { type: string; details: any }) => void;
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
export const fileManager = new FileManager();
|
|
@@ -1,139 +0,0 @@
|
|
|
1
|
-
import { ApplicationMenu, ContextMenu, Tray } from "electrobun/bun";
|
|
2
|
-
|
|
3
|
-
class MenuManager {
|
|
4
|
-
private trays = new Map<number, Tray>();
|
|
5
|
-
private nextTrayId = 1;
|
|
6
|
-
|
|
7
|
-
constructor() {
|
|
8
|
-
this.setupApplicationMenu();
|
|
9
|
-
}
|
|
10
|
-
|
|
11
|
-
private setupApplicationMenu() {
|
|
12
|
-
ApplicationMenu.setApplicationMenu([
|
|
13
|
-
{
|
|
14
|
-
submenu: [
|
|
15
|
-
{ label: "About", role: "about" },
|
|
16
|
-
{ type: "separator" },
|
|
17
|
-
{ label: "Quit", role: "quit", accelerator: "q" }
|
|
18
|
-
],
|
|
19
|
-
},
|
|
20
|
-
{
|
|
21
|
-
label: "Edit",
|
|
22
|
-
submenu: [
|
|
23
|
-
{ role: "undo" },
|
|
24
|
-
{ role: "redo" },
|
|
25
|
-
{ type: "separator" },
|
|
26
|
-
{
|
|
27
|
-
label: "Custom Demo Action",
|
|
28
|
-
action: "demo-action",
|
|
29
|
-
tooltip: "This is a demo menu item",
|
|
30
|
-
},
|
|
31
|
-
{ type: "separator" },
|
|
32
|
-
{ role: "cut" },
|
|
33
|
-
{ role: "copy" },
|
|
34
|
-
{ role: "paste" },
|
|
35
|
-
{ role: "selectAll" },
|
|
36
|
-
],
|
|
37
|
-
},
|
|
38
|
-
{
|
|
39
|
-
label: "View",
|
|
40
|
-
submenu: [
|
|
41
|
-
{ role: "reload" },
|
|
42
|
-
{ role: "forceReload" },
|
|
43
|
-
{ role: "toggleDevTools" },
|
|
44
|
-
{ type: "separator" },
|
|
45
|
-
{ role: "resetZoom" },
|
|
46
|
-
{ role: "zoomIn" },
|
|
47
|
-
{ role: "zoomOut" },
|
|
48
|
-
{ type: "separator" },
|
|
49
|
-
{ role: "togglefullscreen" }
|
|
50
|
-
],
|
|
51
|
-
},
|
|
52
|
-
{
|
|
53
|
-
label: "Window",
|
|
54
|
-
submenu: [
|
|
55
|
-
{ role: "minimize" },
|
|
56
|
-
{ role: "close" }
|
|
57
|
-
],
|
|
58
|
-
}
|
|
59
|
-
]);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
async createTray(options: { title: string; image?: string }) {
|
|
63
|
-
const id = this.nextTrayId++;
|
|
64
|
-
|
|
65
|
-
const tray = new Tray({
|
|
66
|
-
title: options.title,
|
|
67
|
-
image: options.image || "views://assets/tray-icon.png",
|
|
68
|
-
template: true,
|
|
69
|
-
width: 32,
|
|
70
|
-
height: 32,
|
|
71
|
-
});
|
|
72
|
-
|
|
73
|
-
// Set up tray menu
|
|
74
|
-
tray.setMenu([
|
|
75
|
-
{
|
|
76
|
-
type: "normal",
|
|
77
|
-
label: "Show Playground",
|
|
78
|
-
action: "show-playground",
|
|
79
|
-
},
|
|
80
|
-
{
|
|
81
|
-
type: "separator",
|
|
82
|
-
},
|
|
83
|
-
{
|
|
84
|
-
type: "normal",
|
|
85
|
-
label: "Demo Action",
|
|
86
|
-
action: "demo-tray-action",
|
|
87
|
-
tooltip: "This is a demo tray action",
|
|
88
|
-
},
|
|
89
|
-
{
|
|
90
|
-
type: "normal",
|
|
91
|
-
label: "Quit",
|
|
92
|
-
action: "quit-app",
|
|
93
|
-
},
|
|
94
|
-
]);
|
|
95
|
-
|
|
96
|
-
tray.on("tray-clicked", (e) => {
|
|
97
|
-
this.onTrayClicked?.(id, e.data.action);
|
|
98
|
-
});
|
|
99
|
-
|
|
100
|
-
this.trays.set(id, tray);
|
|
101
|
-
return { id };
|
|
102
|
-
}
|
|
103
|
-
|
|
104
|
-
async removeTray(id: number) {
|
|
105
|
-
const tray = this.trays.get(id);
|
|
106
|
-
if (tray) {
|
|
107
|
-
tray.remove();
|
|
108
|
-
this.trays.delete(id);
|
|
109
|
-
}
|
|
110
|
-
}
|
|
111
|
-
|
|
112
|
-
async showContextMenu(params: { x: number; y: number }) {
|
|
113
|
-
ContextMenu.showContextMenu([
|
|
114
|
-
{ role: "undo" },
|
|
115
|
-
{ role: "redo" },
|
|
116
|
-
{ type: "separator" },
|
|
117
|
-
{
|
|
118
|
-
label: "Demo Context Action",
|
|
119
|
-
action: "demo-context-action",
|
|
120
|
-
tooltip: "This is a demo context menu item",
|
|
121
|
-
},
|
|
122
|
-
{
|
|
123
|
-
label: "Disabled Action",
|
|
124
|
-
action: "disabled-action",
|
|
125
|
-
enabled: false,
|
|
126
|
-
},
|
|
127
|
-
{ type: "separator" },
|
|
128
|
-
{ role: "cut" },
|
|
129
|
-
{ role: "copy" },
|
|
130
|
-
{ role: "paste" },
|
|
131
|
-
]);
|
|
132
|
-
}
|
|
133
|
-
|
|
134
|
-
// Event callbacks
|
|
135
|
-
onTrayClicked?: (id: number, action: string) => void;
|
|
136
|
-
onMenuClicked?: (action: string) => void;
|
|
137
|
-
}
|
|
138
|
-
|
|
139
|
-
export const menuManager = new MenuManager();
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
class RPCTester {
|
|
2
|
-
async doMath(data: { a: number; b: number; operation: string }): Promise<number> {
|
|
3
|
-
const startTime = Date.now();
|
|
4
|
-
let result: number;
|
|
5
|
-
|
|
6
|
-
switch (data.operation) {
|
|
7
|
-
case 'add':
|
|
8
|
-
result = data.a + data.b;
|
|
9
|
-
break;
|
|
10
|
-
case 'subtract':
|
|
11
|
-
result = data.a - data.b;
|
|
12
|
-
break;
|
|
13
|
-
case 'multiply':
|
|
14
|
-
result = data.a * data.b;
|
|
15
|
-
break;
|
|
16
|
-
case 'divide':
|
|
17
|
-
if (data.b === 0) throw new Error("Division by zero");
|
|
18
|
-
result = data.a / data.b;
|
|
19
|
-
break;
|
|
20
|
-
case 'power':
|
|
21
|
-
result = Math.pow(data.a, data.b);
|
|
22
|
-
break;
|
|
23
|
-
default:
|
|
24
|
-
throw new Error(`Unknown operation: ${data.operation}`);
|
|
25
|
-
}
|
|
26
|
-
|
|
27
|
-
const duration = Date.now() - startTime;
|
|
28
|
-
|
|
29
|
-
// Don't send notification here - let the frontend handle timing and display
|
|
30
|
-
// to avoid duplicate entries
|
|
31
|
-
|
|
32
|
-
return result;
|
|
33
|
-
}
|
|
34
|
-
|
|
35
|
-
async echoBigData(data: string): Promise<string> {
|
|
36
|
-
const startTime = Date.now();
|
|
37
|
-
|
|
38
|
-
// Simulate some processing time
|
|
39
|
-
await new Promise(resolve => setTimeout(resolve, 100));
|
|
40
|
-
|
|
41
|
-
const response = `Echo: ${data.slice(0, 100)}... (${data.length} chars)`;
|
|
42
|
-
const duration = Date.now() - startTime;
|
|
43
|
-
|
|
44
|
-
// Don't send notification here - let the frontend handle timing and display
|
|
45
|
-
// to avoid duplicate entries
|
|
46
|
-
|
|
47
|
-
return response;
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
async performanceTest(messageSize: number, messageCount: number): Promise<{
|
|
51
|
-
totalTime: number;
|
|
52
|
-
averageTime: number;
|
|
53
|
-
messagesPerSecond: number;
|
|
54
|
-
}> {
|
|
55
|
-
const testData = "x".repeat(messageSize);
|
|
56
|
-
const results: number[] = [];
|
|
57
|
-
|
|
58
|
-
const startTime = Date.now();
|
|
59
|
-
|
|
60
|
-
for (let i = 0; i < messageCount; i++) {
|
|
61
|
-
const messageStart = Date.now();
|
|
62
|
-
await this.echoBigData(testData);
|
|
63
|
-
results.push(Date.now() - messageStart);
|
|
64
|
-
}
|
|
65
|
-
|
|
66
|
-
const totalTime = Date.now() - startTime;
|
|
67
|
-
const averageTime = results.reduce((a, b) => a + b, 0) / results.length;
|
|
68
|
-
const messagesPerSecond = (messageCount / totalTime) * 1000;
|
|
69
|
-
|
|
70
|
-
// Don't send notification here - let the frontend handle timing and display
|
|
71
|
-
|
|
72
|
-
return {
|
|
73
|
-
totalTime,
|
|
74
|
-
averageTime,
|
|
75
|
-
messagesPerSecond
|
|
76
|
-
};
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
// Event callbacks
|
|
80
|
-
onRpcTestResult?: (data: { operation: string; result: any; duration: number }) => void;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
export const rpcTester = new RPCTester();
|
|
@@ -1,72 +0,0 @@
|
|
|
1
|
-
import Electrobun from "electrobun/bun";
|
|
2
|
-
import { platform, arch, release } from "os";
|
|
3
|
-
|
|
4
|
-
class SystemManager {
|
|
5
|
-
async getPlatformInfo() {
|
|
6
|
-
return {
|
|
7
|
-
platform: platform(),
|
|
8
|
-
arch: arch(),
|
|
9
|
-
version: release(),
|
|
10
|
-
electrobunVersion: "0.0.19-beta.118", // This should come from the actual API
|
|
11
|
-
};
|
|
12
|
-
}
|
|
13
|
-
|
|
14
|
-
async showNotification(options: {
|
|
15
|
-
title: string;
|
|
16
|
-
body: string;
|
|
17
|
-
icon?: string;
|
|
18
|
-
}) {
|
|
19
|
-
// Note: Notification API needs to be implemented in Electrobun
|
|
20
|
-
// For now, we'll simulate it
|
|
21
|
-
console.log("Notification:", options);
|
|
22
|
-
|
|
23
|
-
this.onSystemEvent?.({
|
|
24
|
-
type: 'notification-shown',
|
|
25
|
-
details: {
|
|
26
|
-
title: options.title,
|
|
27
|
-
body: options.body,
|
|
28
|
-
timestamp: new Date().toISOString()
|
|
29
|
-
}
|
|
30
|
-
});
|
|
31
|
-
|
|
32
|
-
// In a real implementation, this would use the native notification system
|
|
33
|
-
return Promise.resolve();
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
async getClipboardText(): Promise<string> {
|
|
37
|
-
// Note: Clipboard API needs to be implemented in Electrobun
|
|
38
|
-
// This is a placeholder
|
|
39
|
-
return "Clipboard API not yet implemented";
|
|
40
|
-
}
|
|
41
|
-
|
|
42
|
-
async setClipboardText(text: string): Promise<void> {
|
|
43
|
-
// Note: Clipboard API needs to be implemented in Electrobun
|
|
44
|
-
console.log("Setting clipboard text:", text);
|
|
45
|
-
|
|
46
|
-
this.onSystemEvent?.({
|
|
47
|
-
type: 'clipboard-set',
|
|
48
|
-
details: { text, timestamp: new Date().toISOString() }
|
|
49
|
-
});
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
async getScreenInfo() {
|
|
53
|
-
// Note: Screen API needs to be implemented in Electrobun
|
|
54
|
-
// This is a placeholder
|
|
55
|
-
return {
|
|
56
|
-
displays: [
|
|
57
|
-
{
|
|
58
|
-
id: 1,
|
|
59
|
-
width: 1920,
|
|
60
|
-
height: 1080,
|
|
61
|
-
scaleFactor: 1,
|
|
62
|
-
primary: true
|
|
63
|
-
}
|
|
64
|
-
]
|
|
65
|
-
};
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
// Event callbacks
|
|
69
|
-
onSystemEvent?: (event: { type: string; details: any }) => void;
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
export const systemManager = new SystemManager();
|
|
@@ -1,105 +0,0 @@
|
|
|
1
|
-
import Electrobun from "electrobun/bun";
|
|
2
|
-
|
|
3
|
-
class UpdateManager {
|
|
4
|
-
async checkForUpdates() {
|
|
5
|
-
try {
|
|
6
|
-
const updateInfo = await Electrobun.Updater.checkForUpdate();
|
|
7
|
-
|
|
8
|
-
this.onUpdateStatus?.({
|
|
9
|
-
status: 'checked',
|
|
10
|
-
progress: 100
|
|
11
|
-
});
|
|
12
|
-
|
|
13
|
-
return {
|
|
14
|
-
updateAvailable: updateInfo.updateAvailable,
|
|
15
|
-
currentVersion: Electrobun.Updater.getLocalVersion?.() || "0.0.19-beta.118",
|
|
16
|
-
latestVersion: updateInfo.latestVersion,
|
|
17
|
-
};
|
|
18
|
-
} catch (error) {
|
|
19
|
-
console.error("Update check error:", error);
|
|
20
|
-
|
|
21
|
-
this.onUpdateStatus?.({
|
|
22
|
-
status: 'error',
|
|
23
|
-
progress: 0
|
|
24
|
-
});
|
|
25
|
-
|
|
26
|
-
return {
|
|
27
|
-
updateAvailable: false,
|
|
28
|
-
currentVersion: "0.0.19-beta.118",
|
|
29
|
-
error: error.message
|
|
30
|
-
};
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
|
|
34
|
-
async downloadUpdate() {
|
|
35
|
-
try {
|
|
36
|
-
this.onUpdateStatus?.({
|
|
37
|
-
status: 'downloading',
|
|
38
|
-
progress: 0
|
|
39
|
-
});
|
|
40
|
-
|
|
41
|
-
// Simulate download progress
|
|
42
|
-
for (let i = 0; i <= 100; i += 10) {
|
|
43
|
-
await new Promise(resolve => setTimeout(resolve, 200));
|
|
44
|
-
this.onUpdateStatus?.({
|
|
45
|
-
status: 'downloading',
|
|
46
|
-
progress: i
|
|
47
|
-
});
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
await Electrobun.Updater.downloadUpdate();
|
|
51
|
-
|
|
52
|
-
this.onUpdateStatus?.({
|
|
53
|
-
status: 'downloaded',
|
|
54
|
-
progress: 100
|
|
55
|
-
});
|
|
56
|
-
|
|
57
|
-
return { success: true };
|
|
58
|
-
} catch (error) {
|
|
59
|
-
console.error("Update download error:", error);
|
|
60
|
-
|
|
61
|
-
this.onUpdateStatus?.({
|
|
62
|
-
status: 'error',
|
|
63
|
-
progress: 0
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
return { success: false, error: error.message };
|
|
67
|
-
}
|
|
68
|
-
}
|
|
69
|
-
|
|
70
|
-
async applyUpdate() {
|
|
71
|
-
try {
|
|
72
|
-
this.onUpdateStatus?.({
|
|
73
|
-
status: 'applying',
|
|
74
|
-
progress: 50
|
|
75
|
-
});
|
|
76
|
-
|
|
77
|
-
await Electrobun.Updater.applyUpdate();
|
|
78
|
-
|
|
79
|
-
this.onUpdateStatus?.({
|
|
80
|
-
status: 'applied',
|
|
81
|
-
progress: 100
|
|
82
|
-
});
|
|
83
|
-
|
|
84
|
-
return { success: true };
|
|
85
|
-
} catch (error) {
|
|
86
|
-
console.error("Update apply error:", error);
|
|
87
|
-
|
|
88
|
-
this.onUpdateStatus?.({
|
|
89
|
-
status: 'error',
|
|
90
|
-
progress: 0
|
|
91
|
-
});
|
|
92
|
-
|
|
93
|
-
return { success: false, error: error.message };
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
|
|
97
|
-
getUpdateInfo() {
|
|
98
|
-
return Electrobun.Updater.updateInfo?.() || null;
|
|
99
|
-
}
|
|
100
|
-
|
|
101
|
-
// Event callbacks
|
|
102
|
-
onUpdateStatus?: (data: { status: string; progress?: number }) => void;
|
|
103
|
-
}
|
|
104
|
-
|
|
105
|
-
export const updateManager = new UpdateManager();
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
import { BrowserWindow } from "electrobun/bun";
|
|
2
|
-
|
|
3
|
-
class WindowManager {
|
|
4
|
-
private windows = new Map<number, BrowserWindow>();
|
|
5
|
-
private nextId = 1;
|
|
6
|
-
|
|
7
|
-
async createWindow(options: {
|
|
8
|
-
width: number;
|
|
9
|
-
height: number;
|
|
10
|
-
x: number;
|
|
11
|
-
y: number;
|
|
12
|
-
frameless?: boolean;
|
|
13
|
-
transparent?: boolean;
|
|
14
|
-
alwaysOnTop?: boolean;
|
|
15
|
-
}) {
|
|
16
|
-
const id = this.nextId++;
|
|
17
|
-
|
|
18
|
-
const window = new BrowserWindow({
|
|
19
|
-
title: `Demo Window ${id}`,
|
|
20
|
-
url: "views://mainview/index.html",
|
|
21
|
-
renderer: "cef",
|
|
22
|
-
frame: {
|
|
23
|
-
width: options.width,
|
|
24
|
-
height: options.height,
|
|
25
|
-
x: options.x,
|
|
26
|
-
y: options.y,
|
|
27
|
-
},
|
|
28
|
-
titleBarStyle: options.frameless ? "hiddenInset" : "default",
|
|
29
|
-
// For completely frameless, we need to set styleMask
|
|
30
|
-
styleMask: options.frameless ? {
|
|
31
|
-
Borderless: true,
|
|
32
|
-
Titled: false,
|
|
33
|
-
Closable: true,
|
|
34
|
-
Miniaturizable: true,
|
|
35
|
-
Resizable: true,
|
|
36
|
-
} : undefined,
|
|
37
|
-
});
|
|
38
|
-
|
|
39
|
-
this.windows.set(id, window);
|
|
40
|
-
|
|
41
|
-
// Listen for window events
|
|
42
|
-
window.on("close", () => {
|
|
43
|
-
this.windows.delete(id);
|
|
44
|
-
this.onWindowClosed?.(id);
|
|
45
|
-
});
|
|
46
|
-
|
|
47
|
-
window.on("resize", (event) => {
|
|
48
|
-
this.onWindowEvent?.({ type: 'resize', id, data: event.data });
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
window.on("move", (event) => {
|
|
52
|
-
this.onWindowEvent?.({ type: 'move', id, data: event.data });
|
|
53
|
-
});
|
|
54
|
-
|
|
55
|
-
this.onWindowCreated?.(id, `Demo Window ${id}`);
|
|
56
|
-
|
|
57
|
-
return { id };
|
|
58
|
-
}
|
|
59
|
-
|
|
60
|
-
async closeWindow(id: number) {
|
|
61
|
-
const window = this.windows.get(id);
|
|
62
|
-
if (window) {
|
|
63
|
-
window.close();
|
|
64
|
-
this.windows.delete(id);
|
|
65
|
-
}
|
|
66
|
-
}
|
|
67
|
-
|
|
68
|
-
async focusWindow(id: number) {
|
|
69
|
-
const window = this.windows.get(id);
|
|
70
|
-
if (window) {
|
|
71
|
-
window.focus();
|
|
72
|
-
this.onWindowFocused?.(id);
|
|
73
|
-
}
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
async getWindowList() {
|
|
77
|
-
return Array.from(this.windows.entries()).map(([id, window]) => ({
|
|
78
|
-
id,
|
|
79
|
-
title: window.getTitle() || `Window ${id}`,
|
|
80
|
-
}));
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
// Event callbacks
|
|
84
|
-
onWindowCreated?: (id: number, title: string) => void;
|
|
85
|
-
onWindowClosed?: (id: number) => void;
|
|
86
|
-
onWindowFocused?: (id: number) => void;
|
|
87
|
-
onWindowEvent?: (event: { type: string; id: number; data: any }) => void;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
export const windowManager = new WindowManager();
|
|
@@ -1,124 +0,0 @@
|
|
|
1
|
-
import Electrobun, { BrowserWindow, BrowserView } from "electrobun/bun";
|
|
2
|
-
import { type PlaygroundRPC } from "./types/rpc";
|
|
3
|
-
|
|
4
|
-
// Import demo modules
|
|
5
|
-
import { windowManager } from "./demos/windows";
|
|
6
|
-
import { menuManager } from "./demos/menus";
|
|
7
|
-
import { fileManager } from "./demos/files";
|
|
8
|
-
import { rpcTester } from "./demos/rpc";
|
|
9
|
-
|
|
10
|
-
console.log("🚀 Electrobun Interactive Playground starting...");
|
|
11
|
-
|
|
12
|
-
// Set up RPC communication
|
|
13
|
-
const rpc = BrowserView.defineRPC<PlaygroundRPC>({
|
|
14
|
-
maxRequestTime: 10000,
|
|
15
|
-
handlers: {
|
|
16
|
-
requests: {
|
|
17
|
-
// Window Management
|
|
18
|
-
createWindow: windowManager.createWindow.bind(windowManager),
|
|
19
|
-
closeWindow: windowManager.closeWindow.bind(windowManager),
|
|
20
|
-
focusWindow: windowManager.focusWindow.bind(windowManager),
|
|
21
|
-
getWindowList: windowManager.getWindowList.bind(windowManager),
|
|
22
|
-
|
|
23
|
-
// RPC Testing
|
|
24
|
-
doMath: rpcTester.doMath.bind(rpcTester),
|
|
25
|
-
echoBigData: rpcTester.echoBigData.bind(rpcTester),
|
|
26
|
-
|
|
27
|
-
// Menu Operations
|
|
28
|
-
createTray: menuManager.createTray.bind(menuManager),
|
|
29
|
-
removeTray: menuManager.removeTray.bind(menuManager),
|
|
30
|
-
showContextMenu: menuManager.showContextMenu.bind(menuManager),
|
|
31
|
-
|
|
32
|
-
// File Operations
|
|
33
|
-
openFileDialog: fileManager.openFileDialog.bind(fileManager),
|
|
34
|
-
moveToTrash: fileManager.moveToTrash.bind(fileManager),
|
|
35
|
-
showInFinder: fileManager.showInFinder.bind(fileManager),
|
|
36
|
-
|
|
37
|
-
// WebView Operations (placeholder)
|
|
38
|
-
createWebView: async (url: string) => ({ id: 1 }),
|
|
39
|
-
executeJSInWebView: async (params: { id: number; script: string }) => null,
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
},
|
|
43
|
-
messages: {
|
|
44
|
-
"*": (messageName, payload) => {
|
|
45
|
-
console.log(`📨 Message received: ${messageName}`, payload);
|
|
46
|
-
},
|
|
47
|
-
},
|
|
48
|
-
},
|
|
49
|
-
});
|
|
50
|
-
|
|
51
|
-
// Create main playground window
|
|
52
|
-
const mainWindow = new BrowserWindow({
|
|
53
|
-
title: "Electrobun Interactive Playground",
|
|
54
|
-
url: "views://mainview/index.html",
|
|
55
|
-
renderer: "cef",
|
|
56
|
-
frame: {
|
|
57
|
-
width: 1400,
|
|
58
|
-
height: 900,
|
|
59
|
-
x: 100,
|
|
60
|
-
y: 100,
|
|
61
|
-
},
|
|
62
|
-
titleBarStyle: "default",
|
|
63
|
-
rpc,
|
|
64
|
-
});
|
|
65
|
-
|
|
66
|
-
// Set up event forwarding from demo modules to the UI
|
|
67
|
-
windowManager.onWindowCreated = (id, title) => {
|
|
68
|
-
rpc.send.windowCreated({ id, title });
|
|
69
|
-
};
|
|
70
|
-
|
|
71
|
-
windowManager.onWindowClosed = (id) => {
|
|
72
|
-
rpc.send.windowClosed({ id });
|
|
73
|
-
};
|
|
74
|
-
|
|
75
|
-
windowManager.onWindowFocused = (id) => {
|
|
76
|
-
rpc.send.windowFocused({ id });
|
|
77
|
-
};
|
|
78
|
-
|
|
79
|
-
menuManager.onTrayClicked = (id, action) => {
|
|
80
|
-
rpc.send.trayClicked({ id, action });
|
|
81
|
-
console.log(`🔔 Tray ${id} clicked: ${action}`);
|
|
82
|
-
};
|
|
83
|
-
|
|
84
|
-
menuManager.onMenuClicked = (action) => {
|
|
85
|
-
rpc.send.menuClicked({ action });
|
|
86
|
-
console.log(`🎛️ Menu clicked: ${action}`);
|
|
87
|
-
};
|
|
88
|
-
|
|
89
|
-
fileManager.onFileSelected = (paths) => {
|
|
90
|
-
rpc.send.fileSelected({ paths });
|
|
91
|
-
console.log(`📁 Files selected:`, paths);
|
|
92
|
-
};
|
|
93
|
-
|
|
94
|
-
fileManager.onSystemEvent = (event) => {
|
|
95
|
-
rpc.send.systemEvent(event);
|
|
96
|
-
console.log(`⚙️ System event:`, event);
|
|
97
|
-
};
|
|
98
|
-
|
|
99
|
-
rpcTester.onRpcTestResult = (data) => {
|
|
100
|
-
rpc.send.rpcTestResult(data);
|
|
101
|
-
console.log(`📡 RPC test result:`, data);
|
|
102
|
-
};
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
// Listen for global events
|
|
107
|
-
Electrobun.events.on("application-menu-clicked", (e) => {
|
|
108
|
-
menuManager.onMenuClicked?.(e.data.action);
|
|
109
|
-
});
|
|
110
|
-
|
|
111
|
-
Electrobun.events.on("context-menu-clicked", (e) => {
|
|
112
|
-
menuManager.onMenuClicked?.(e.data.action);
|
|
113
|
-
});
|
|
114
|
-
|
|
115
|
-
// Send initial status
|
|
116
|
-
mainWindow.webview.on("dom-ready", () => {
|
|
117
|
-
console.log("✅ Main window DOM ready");
|
|
118
|
-
rpc.send.logMessage({
|
|
119
|
-
level: 'info',
|
|
120
|
-
message: 'Electrobun Interactive Playground loaded successfully!'
|
|
121
|
-
});
|
|
122
|
-
});
|
|
123
|
-
|
|
124
|
-
console.log("🎮 Playground initialized successfully");
|