electrobun 0.5.0-beta.0 → 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,229 +0,0 @@
|
|
|
1
|
-
export class RPCDemo {
|
|
2
|
-
private testResults: Array<{ operation: string; result: any; duration: number }> = [];
|
|
3
|
-
|
|
4
|
-
render() {
|
|
5
|
-
return `
|
|
6
|
-
<div class="demo-section">
|
|
7
|
-
<div class="demo-header">
|
|
8
|
-
<span class="demo-icon">📡</span>
|
|
9
|
-
<div>
|
|
10
|
-
<h2 class="demo-title">RPC Communication</h2>
|
|
11
|
-
<p class="demo-description">Test bidirectional communication between the webview and bun process</p>
|
|
12
|
-
</div>
|
|
13
|
-
</div>
|
|
14
|
-
|
|
15
|
-
<div class="demo-controls">
|
|
16
|
-
<h3>Math Operations</h3>
|
|
17
|
-
<div class="control-group">
|
|
18
|
-
<label class="control-label">A:</label>
|
|
19
|
-
<input type="number" id="math-a" class="control-input" value="10">
|
|
20
|
-
|
|
21
|
-
<label class="control-label">B:</label>
|
|
22
|
-
<input type="number" id="math-b" class="control-input" value="5">
|
|
23
|
-
|
|
24
|
-
<label class="control-label">Operation:</label>
|
|
25
|
-
<select id="math-operation" class="control-input" style="width: 120px;">
|
|
26
|
-
<option value="add">Add (+)</option>
|
|
27
|
-
<option value="subtract">Subtract (-)</option>
|
|
28
|
-
<option value="multiply">Multiply (×)</option>
|
|
29
|
-
<option value="divide">Divide (÷)</option>
|
|
30
|
-
<option value="power">Power (^)</option>
|
|
31
|
-
</select>
|
|
32
|
-
|
|
33
|
-
<button class="btn btn-primary" id="do-math">Calculate</button>
|
|
34
|
-
</div>
|
|
35
|
-
|
|
36
|
-
<h3>Data Transfer Test</h3>
|
|
37
|
-
<div class="control-group">
|
|
38
|
-
<label class="control-label">Data Size:</label>
|
|
39
|
-
<select id="data-size" class="control-input" style="width: 150px;">
|
|
40
|
-
<option value="1024">1 KB</option>
|
|
41
|
-
<option value="10240">10 KB</option>
|
|
42
|
-
<option value="102400">100 KB</option>
|
|
43
|
-
<option value="1048576">1 MB</option>
|
|
44
|
-
<option value="2097152">2 MB</option>
|
|
45
|
-
</select>
|
|
46
|
-
|
|
47
|
-
<button class="btn btn-primary" id="test-big-data">Test Echo</button>
|
|
48
|
-
</div>
|
|
49
|
-
|
|
50
|
-
<h3>Performance Test</h3>
|
|
51
|
-
<div class="control-group">
|
|
52
|
-
<label class="control-label">Message Size:</label>
|
|
53
|
-
<select id="perf-size" class="control-input" style="width: 120px;">
|
|
54
|
-
<option value="100">100 B</option>
|
|
55
|
-
<option value="1024">1 KB</option>
|
|
56
|
-
<option value="10240">10 KB</option>
|
|
57
|
-
</select>
|
|
58
|
-
|
|
59
|
-
<label class="control-label">Count:</label>
|
|
60
|
-
<input type="number" id="perf-count" class="control-input" value="10" min="1" max="100">
|
|
61
|
-
|
|
62
|
-
<button class="btn btn-primary" id="run-performance-test">Run Test</button>
|
|
63
|
-
</div>
|
|
64
|
-
</div>
|
|
65
|
-
|
|
66
|
-
<div class="demo-results">
|
|
67
|
-
<div class="results-header">Test Results:</div>
|
|
68
|
-
<div id="rpc-results" class="rpc-results">
|
|
69
|
-
<div class="no-results" style="text-align: center; color: #718096; padding: 2rem;">
|
|
70
|
-
No tests run yet. Use the controls above to start testing RPC communication.
|
|
71
|
-
</div>
|
|
72
|
-
</div>
|
|
73
|
-
</div>
|
|
74
|
-
</div>
|
|
75
|
-
`;
|
|
76
|
-
}
|
|
77
|
-
|
|
78
|
-
initialize(rpc: any) {
|
|
79
|
-
const mathBtn = document.getElementById('do-math');
|
|
80
|
-
const bigDataBtn = document.getElementById('test-big-data');
|
|
81
|
-
const perfTestBtn = document.getElementById('run-performance-test');
|
|
82
|
-
|
|
83
|
-
mathBtn?.addEventListener('click', async () => {
|
|
84
|
-
const a = parseFloat((document.getElementById('math-a') as HTMLInputElement).value);
|
|
85
|
-
const b = parseFloat((document.getElementById('math-b') as HTMLInputElement).value);
|
|
86
|
-
const operation = (document.getElementById('math-operation') as HTMLSelectElement).value;
|
|
87
|
-
|
|
88
|
-
try {
|
|
89
|
-
const startTime = Date.now();
|
|
90
|
-
const result = await rpc.request.doMath({ a, b, operation });
|
|
91
|
-
const duration = Date.now() - startTime;
|
|
92
|
-
|
|
93
|
-
this.addTestResult({
|
|
94
|
-
operation: `${a} ${operation} ${b}`,
|
|
95
|
-
result,
|
|
96
|
-
duration
|
|
97
|
-
});
|
|
98
|
-
} catch (error) {
|
|
99
|
-
this.addTestResult({
|
|
100
|
-
operation: `${a} ${operation} ${b}`,
|
|
101
|
-
result: `Error: ${error.message}`,
|
|
102
|
-
duration: 0
|
|
103
|
-
});
|
|
104
|
-
}
|
|
105
|
-
});
|
|
106
|
-
|
|
107
|
-
bigDataBtn?.addEventListener('click', async () => {
|
|
108
|
-
const size = parseInt((document.getElementById('data-size') as HTMLSelectElement).value);
|
|
109
|
-
const testData = 'x'.repeat(size);
|
|
110
|
-
|
|
111
|
-
try {
|
|
112
|
-
const startTime = Date.now();
|
|
113
|
-
const result = await rpc.request.echoBigData(testData);
|
|
114
|
-
const duration = Date.now() - startTime;
|
|
115
|
-
|
|
116
|
-
this.addTestResult({
|
|
117
|
-
operation: `Echo ${this.formatBytes(size)}`,
|
|
118
|
-
result: `Received ${this.formatBytes(result.length)}`,
|
|
119
|
-
duration
|
|
120
|
-
});
|
|
121
|
-
} catch (error) {
|
|
122
|
-
this.addTestResult({
|
|
123
|
-
operation: `Echo ${this.formatBytes(size)}`,
|
|
124
|
-
result: `Error: ${error.message}`,
|
|
125
|
-
duration: 0
|
|
126
|
-
});
|
|
127
|
-
}
|
|
128
|
-
});
|
|
129
|
-
|
|
130
|
-
perfTestBtn?.addEventListener('click', async () => {
|
|
131
|
-
const size = parseInt((document.getElementById('perf-size') as HTMLSelectElement).value);
|
|
132
|
-
const count = parseInt((document.getElementById('perf-count') as HTMLInputElement).value);
|
|
133
|
-
|
|
134
|
-
perfTestBtn.textContent = 'Running...';
|
|
135
|
-
perfTestBtn.setAttribute('disabled', 'true');
|
|
136
|
-
|
|
137
|
-
try {
|
|
138
|
-
const results = await this.runPerformanceTest(rpc, size, count);
|
|
139
|
-
this.addTestResult({
|
|
140
|
-
operation: `Performance: ${count} × ${this.formatBytes(size)}`,
|
|
141
|
-
result: `${results.messagesPerSecond.toFixed(1)} msg/sec, avg: ${results.averageTime.toFixed(1)}ms`,
|
|
142
|
-
duration: results.totalTime
|
|
143
|
-
});
|
|
144
|
-
} catch (error) {
|
|
145
|
-
this.addTestResult({
|
|
146
|
-
operation: `Performance: ${count} × ${this.formatBytes(size)}`,
|
|
147
|
-
result: `Error: ${error.message}`,
|
|
148
|
-
duration: 0
|
|
149
|
-
});
|
|
150
|
-
} finally {
|
|
151
|
-
perfTestBtn.textContent = 'Run Test';
|
|
152
|
-
perfTestBtn.removeAttribute('disabled');
|
|
153
|
-
}
|
|
154
|
-
});
|
|
155
|
-
}
|
|
156
|
-
|
|
157
|
-
private async runPerformanceTest(rpc: any, messageSize: number, messageCount: number) {
|
|
158
|
-
const testData = 'x'.repeat(messageSize);
|
|
159
|
-
const results: number[] = [];
|
|
160
|
-
const startTime = Date.now();
|
|
161
|
-
|
|
162
|
-
for (let i = 0; i < messageCount; i++) {
|
|
163
|
-
const messageStart = Date.now();
|
|
164
|
-
await rpc.request.echoBigData(testData);
|
|
165
|
-
results.push(Date.now() - messageStart);
|
|
166
|
-
|
|
167
|
-
// Update progress
|
|
168
|
-
const progress = ((i + 1) / messageCount) * 100;
|
|
169
|
-
const perfTestBtn = document.getElementById('run-performance-test');
|
|
170
|
-
if (perfTestBtn) {
|
|
171
|
-
perfTestBtn.textContent = `Running... ${progress.toFixed(0)}%`;
|
|
172
|
-
}
|
|
173
|
-
}
|
|
174
|
-
|
|
175
|
-
const totalTime = Date.now() - startTime;
|
|
176
|
-
const averageTime = results.reduce((a, b) => a + b, 0) / results.length;
|
|
177
|
-
const messagesPerSecond = (messageCount / totalTime) * 1000;
|
|
178
|
-
|
|
179
|
-
return { totalTime, averageTime, messagesPerSecond };
|
|
180
|
-
}
|
|
181
|
-
|
|
182
|
-
private addTestResult(result: { operation: string; result: any; duration: number }) {
|
|
183
|
-
this.testResults.unshift(result);
|
|
184
|
-
|
|
185
|
-
// Keep only last 20 results
|
|
186
|
-
if (this.testResults.length > 20) {
|
|
187
|
-
this.testResults = this.testResults.slice(0, 20);
|
|
188
|
-
}
|
|
189
|
-
|
|
190
|
-
this.renderResults();
|
|
191
|
-
}
|
|
192
|
-
|
|
193
|
-
private renderResults() {
|
|
194
|
-
const container = document.getElementById('rpc-results');
|
|
195
|
-
if (!container) return;
|
|
196
|
-
|
|
197
|
-
if (this.testResults.length === 0) {
|
|
198
|
-
container.innerHTML = `
|
|
199
|
-
<div class="no-results" style="text-align: center; color: #718096; padding: 2rem;">
|
|
200
|
-
No tests run yet. Use the controls above to start testing RPC communication.
|
|
201
|
-
</div>
|
|
202
|
-
`;
|
|
203
|
-
return;
|
|
204
|
-
}
|
|
205
|
-
|
|
206
|
-
container.innerHTML = this.testResults.map(result => `
|
|
207
|
-
<div class="result-entry" style="background: #f8fafc; border-left: 3px solid #4299e1; padding: 1rem; margin-bottom: 0.5rem; border-radius: 0 0.25rem 0.25rem 0;">
|
|
208
|
-
<div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 0.5rem;">
|
|
209
|
-
<strong>${result.operation}</strong>
|
|
210
|
-
<span style="color: #718096; font-size: 0.875rem;">${result.duration}ms</span>
|
|
211
|
-
</div>
|
|
212
|
-
<div style="color: #2d3748;">${result.result}</div>
|
|
213
|
-
</div>
|
|
214
|
-
`).join('');
|
|
215
|
-
}
|
|
216
|
-
|
|
217
|
-
private formatBytes(bytes: number): string {
|
|
218
|
-
if (bytes === 0) return '0 B';
|
|
219
|
-
const k = 1024;
|
|
220
|
-
const sizes = ['B', 'KB', 'MB', 'GB'];
|
|
221
|
-
const i = Math.floor(Math.log(bytes) / Math.log(k));
|
|
222
|
-
return parseFloat((bytes / Math.pow(k, i)).toFixed(1)) + ' ' + sizes[i];
|
|
223
|
-
}
|
|
224
|
-
|
|
225
|
-
// Handle events from the backend
|
|
226
|
-
onRpcTestResult(data: { operation: string; result: any; duration: number }) {
|
|
227
|
-
this.addTestResult(data);
|
|
228
|
-
}
|
|
229
|
-
}
|
|
@@ -1,132 +0,0 @@
|
|
|
1
|
-
export class TrayDemo {
|
|
2
|
-
private trays: Array<{ id: number; title: string }> = [];
|
|
3
|
-
private rpc: any;
|
|
4
|
-
|
|
5
|
-
render() {
|
|
6
|
-
return `
|
|
7
|
-
<div class="demo-section">
|
|
8
|
-
<div class="demo-header">
|
|
9
|
-
<span class="demo-icon">🔔</span>
|
|
10
|
-
<div>
|
|
11
|
-
<h2 class="demo-title">System Tray</h2>
|
|
12
|
-
<p class="demo-description">Create and manage system tray icons with menus</p>
|
|
13
|
-
</div>
|
|
14
|
-
</div>
|
|
15
|
-
|
|
16
|
-
<div class="demo-controls">
|
|
17
|
-
<h3>Create System Tray</h3>
|
|
18
|
-
<div class="control-group">
|
|
19
|
-
<label class="control-label">Title:</label>
|
|
20
|
-
<input type="text" id="tray-title" class="control-input" value="My Tray Item" style="width: 200px;">
|
|
21
|
-
|
|
22
|
-
<button class="btn btn-primary" id="create-tray">Create Tray</button>
|
|
23
|
-
<button class="btn btn-danger" id="remove-all-trays">Remove All Trays</button>
|
|
24
|
-
</div>
|
|
25
|
-
|
|
26
|
-
<div style="margin-top: 1rem; padding: 1rem; background: #f7fafc; border-radius: 0.5rem;">
|
|
27
|
-
<p style="color: #4a5568; font-size: 0.875rem;">
|
|
28
|
-
<strong>Note:</strong> System tray icons appear in your system's menu bar or notification area.
|
|
29
|
-
Click on the tray icon to see its menu. On macOS, look in the top-right menu bar.
|
|
30
|
-
</p>
|
|
31
|
-
</div>
|
|
32
|
-
</div>
|
|
33
|
-
|
|
34
|
-
<div class="demo-results">
|
|
35
|
-
<div class="results-header">Active Trays (<span id="tray-count">0</span>):</div>
|
|
36
|
-
<div id="tray-list" class="tray-list">
|
|
37
|
-
<div class="no-trays" style="text-align: center; color: #718096; padding: 2rem;">
|
|
38
|
-
No system tray items created yet.
|
|
39
|
-
</div>
|
|
40
|
-
</div>
|
|
41
|
-
</div>
|
|
42
|
-
</div>
|
|
43
|
-
`;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
initialize(rpc: any) {
|
|
47
|
-
this.rpc = rpc;
|
|
48
|
-
|
|
49
|
-
const createTrayBtn = document.getElementById('create-tray');
|
|
50
|
-
const removeAllTraysBtn = document.getElementById('remove-all-trays');
|
|
51
|
-
|
|
52
|
-
createTrayBtn?.addEventListener('click', async () => {
|
|
53
|
-
const title = (document.getElementById('tray-title') as HTMLInputElement).value;
|
|
54
|
-
|
|
55
|
-
try {
|
|
56
|
-
const result = await rpc.request.createTray({ title });
|
|
57
|
-
this.trays.push({ id: result.id, title });
|
|
58
|
-
this.updateTrayList();
|
|
59
|
-
console.log('Created tray:', result);
|
|
60
|
-
} catch (error) {
|
|
61
|
-
console.error('Error creating tray:', error);
|
|
62
|
-
}
|
|
63
|
-
});
|
|
64
|
-
|
|
65
|
-
removeAllTraysBtn?.addEventListener('click', async () => {
|
|
66
|
-
for (const tray of this.trays) {
|
|
67
|
-
try {
|
|
68
|
-
await rpc.request.removeTray(tray.id);
|
|
69
|
-
console.log('Removed tray:', tray.id);
|
|
70
|
-
} catch (error) {
|
|
71
|
-
console.error(`Error removing tray ${tray.id}:`, error);
|
|
72
|
-
}
|
|
73
|
-
}
|
|
74
|
-
this.trays = [];
|
|
75
|
-
this.updateTrayList();
|
|
76
|
-
});
|
|
77
|
-
}
|
|
78
|
-
|
|
79
|
-
private updateTrayList() {
|
|
80
|
-
const container = document.getElementById('tray-list');
|
|
81
|
-
const count = document.getElementById('tray-count');
|
|
82
|
-
|
|
83
|
-
if (!container || !count) return;
|
|
84
|
-
|
|
85
|
-
count.textContent = this.trays.length.toString();
|
|
86
|
-
|
|
87
|
-
if (this.trays.length === 0) {
|
|
88
|
-
container.innerHTML = `
|
|
89
|
-
<div class="no-trays" style="text-align: center; color: #718096; padding: 2rem;">
|
|
90
|
-
No system tray items created yet.
|
|
91
|
-
</div>
|
|
92
|
-
`;
|
|
93
|
-
return;
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
container.innerHTML = this.trays.map(tray => `
|
|
97
|
-
<div class="tray-item" style="background: #f8fafc; border: 1px solid #e2e8f0; border-radius: 0.5rem; padding: 1rem; margin-bottom: 0.5rem;">
|
|
98
|
-
<div style="display: flex; justify-content: space-between; align-items: center;">
|
|
99
|
-
<div>
|
|
100
|
-
<strong>Tray ${tray.id}</strong>
|
|
101
|
-
<div style="color: #718096; font-size: 0.875rem;">${tray.title}</div>
|
|
102
|
-
<div style="color: #4299e1; font-size: 0.75rem; margin-top: 0.25rem;">
|
|
103
|
-
Click tray icon in menu bar to see menu
|
|
104
|
-
</div>
|
|
105
|
-
</div>
|
|
106
|
-
<button class="btn btn-small btn-danger remove-tray" data-tray-id="${tray.id}">Remove</button>
|
|
107
|
-
</div>
|
|
108
|
-
</div>
|
|
109
|
-
`).join('');
|
|
110
|
-
|
|
111
|
-
// Add remove button listeners
|
|
112
|
-
const removeButtons = document.querySelectorAll('.remove-tray');
|
|
113
|
-
removeButtons.forEach(btn => {
|
|
114
|
-
btn.addEventListener('click', async (e) => {
|
|
115
|
-
const id = parseInt((e.target as HTMLElement).getAttribute('data-tray-id') || '0');
|
|
116
|
-
try {
|
|
117
|
-
await this.rpc.request.removeTray(id);
|
|
118
|
-
console.log('Removed tray:', id);
|
|
119
|
-
this.trays = this.trays.filter(t => t.id !== id);
|
|
120
|
-
this.updateTrayList();
|
|
121
|
-
} catch (error) {
|
|
122
|
-
console.error(`Error removing tray ${id}:`, error);
|
|
123
|
-
}
|
|
124
|
-
});
|
|
125
|
-
});
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
// Handle events from the backend
|
|
129
|
-
onTrayClicked(data: { id: number; action: string }) {
|
|
130
|
-
console.log('Tray clicked:', data);
|
|
131
|
-
}
|
|
132
|
-
}
|