electrobun 0.1.2 → 0.1.7
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +10 -2
- package/dist/api/browser/webviewtag.ts +37 -23
- package/dist/api/bun/core/BrowserView.ts +2 -5
- package/dist/api/bun/core/BrowserWindow.ts +1 -2
- package/dist/api/bun/core/Tray.ts +21 -12
- package/dist/api/bun/core/Utils.ts +6 -1
- package/dist/api/bun/proc/native.ts +13 -15
- package/package.json +3 -2
package/README.md
CHANGED
|
@@ -8,7 +8,7 @@
|
|
|
8
8
|
|
|
9
9
|
## What is Electrobun?
|
|
10
10
|
|
|
11
|
-
> Electrobun is in the **_very_** early stages. We currently support development on macOS, Windows, and Linux
|
|
11
|
+
> Electrobun is in the **_very_** early stages. We currently support development on macOS, Windows, and Linux. You can also bundle your app for these platform targets and cross-bundle them from a mac. We're actively working on stabilizing so any bug reports, especially on different platforms are most welcome.
|
|
12
12
|
|
|
13
13
|
Electrobun aims to be a complete **solution-in-a-box** for building, updating, and shipping ultra fast, tiny, and cross-platform desktop applications written in Typescript.
|
|
14
14
|
Under the hood it uses <a href="https://bun.sh">bun</a> to execute the main process and to bundle webview typescript, and has native bindings written in <a href="https://ziglang.org/">zig</a>.
|
|
@@ -60,13 +60,17 @@ Ways to get involved at this early stage:
|
|
|
60
60
|
- cmake
|
|
61
61
|
- webkit2gtk and GTK development packages
|
|
62
62
|
|
|
63
|
+
Un Ubuntu/Debian based distros: `sudo apt install build-essential cmake pkg-config libgtk-3-dev libwebkit2gtk-4.1-dev libayatana-appindicator3-dev librsvg2-dev`
|
|
64
|
+
|
|
63
65
|
### First-time Setup
|
|
64
66
|
|
|
65
67
|
```bash
|
|
66
|
-
git clone
|
|
68
|
+
git clone --recurse-submodules https://github.com/blackboardsh/electrobun.git
|
|
67
69
|
cd electrobun
|
|
68
70
|
bun install
|
|
69
71
|
bun dev:playground:clean
|
|
72
|
+
# On Linux, use:
|
|
73
|
+
bun dev:playground:clean:linux
|
|
70
74
|
```
|
|
71
75
|
|
|
72
76
|
### Development Workflow
|
|
@@ -74,12 +78,16 @@ bun dev:playground:clean
|
|
|
74
78
|
```bash
|
|
75
79
|
# After making changes to source code
|
|
76
80
|
bun dev:playground
|
|
81
|
+
# On Linux, use:
|
|
82
|
+
bun dev:playground:linux
|
|
77
83
|
|
|
78
84
|
# If you only changed playground code (not electrobun source)
|
|
79
85
|
bun dev:playground:rerun
|
|
80
86
|
|
|
81
87
|
# If you need a completely fresh start
|
|
82
88
|
bun dev:playground:clean
|
|
89
|
+
# On Linux, use:
|
|
90
|
+
bun dev:playground:clean:linux
|
|
83
91
|
```
|
|
84
92
|
|
|
85
93
|
### Additional Commands
|
|
@@ -111,7 +111,7 @@ const ConfigureWebviewTags = (
|
|
|
111
111
|
// todo: wire up to a param and a method to update them
|
|
112
112
|
navigationRules: null,
|
|
113
113
|
});
|
|
114
|
-
|
|
114
|
+
console.log('electrobun webviewid: ', webviewId)
|
|
115
115
|
this.webviewId = webviewId;
|
|
116
116
|
this.id = `electrobun-webview-${webviewId}`;
|
|
117
117
|
// todo: replace bun -> webviewtag communication with a global instead of
|
|
@@ -252,8 +252,10 @@ const ConfigureWebviewTags = (
|
|
|
252
252
|
|
|
253
253
|
if (width === 0 && height === 0) {
|
|
254
254
|
if (this.wasZeroRect === false) {
|
|
255
|
+
console.log('WAS NOT ZERO RECT', this.webviewId)
|
|
255
256
|
this.wasZeroRect = true;
|
|
256
|
-
this.
|
|
257
|
+
this.toggleTransparent(true, true);
|
|
258
|
+
this.togglePassthrough(true, true);
|
|
257
259
|
}
|
|
258
260
|
return;
|
|
259
261
|
}
|
|
@@ -312,7 +314,9 @@ const ConfigureWebviewTags = (
|
|
|
312
314
|
|
|
313
315
|
if (this.wasZeroRect) {
|
|
314
316
|
this.wasZeroRect = false;
|
|
315
|
-
|
|
317
|
+
console.log('WAS ZERO RECT', this.webviewId)
|
|
318
|
+
this.toggleTransparent(false, true);
|
|
319
|
+
this.togglePassthrough(false, true);
|
|
316
320
|
}
|
|
317
321
|
}
|
|
318
322
|
|
|
@@ -492,17 +496,20 @@ const ConfigureWebviewTags = (
|
|
|
492
496
|
return;
|
|
493
497
|
}
|
|
494
498
|
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
}
|
|
499
|
+
let newValue;
|
|
500
|
+
if (typeof transparent === "undefined") {
|
|
501
|
+
newValue = !this.transparent;
|
|
502
|
+
} else {
|
|
503
|
+
newValue = Boolean(transparent);
|
|
501
504
|
}
|
|
502
505
|
|
|
506
|
+
if (!bypassState) {
|
|
507
|
+
this.transparent = newValue;
|
|
508
|
+
}
|
|
509
|
+
|
|
503
510
|
this.internalRpc.send.webviewTagSetTransparent({
|
|
504
511
|
id: this.webviewId,
|
|
505
|
-
transparent:
|
|
512
|
+
transparent: newValue,
|
|
506
513
|
});
|
|
507
514
|
}
|
|
508
515
|
togglePassthrough(enablePassthrough?: boolean, bypassState?: boolean) {
|
|
@@ -511,12 +518,15 @@ const ConfigureWebviewTags = (
|
|
|
511
518
|
return;
|
|
512
519
|
}
|
|
513
520
|
|
|
514
|
-
|
|
515
|
-
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
|
|
519
|
-
|
|
521
|
+
let newValue;
|
|
522
|
+
if (typeof enablePassthrough === "undefined") {
|
|
523
|
+
newValue = !this.passthroughEnabled;
|
|
524
|
+
} else {
|
|
525
|
+
newValue = Boolean(enablePassthrough);
|
|
526
|
+
}
|
|
527
|
+
|
|
528
|
+
if (!bypassState) {
|
|
529
|
+
this.passthroughEnabled = newValue;
|
|
520
530
|
}
|
|
521
531
|
|
|
522
532
|
this.internalRpc.send.webviewTagSetPassthrough({
|
|
@@ -532,17 +542,21 @@ const ConfigureWebviewTags = (
|
|
|
532
542
|
return;
|
|
533
543
|
}
|
|
534
544
|
|
|
535
|
-
|
|
536
|
-
|
|
537
|
-
|
|
538
|
-
|
|
539
|
-
|
|
540
|
-
|
|
545
|
+
let newValue;
|
|
546
|
+
if (typeof hidden === "undefined") {
|
|
547
|
+
newValue = !this.hidden;
|
|
548
|
+
} else {
|
|
549
|
+
newValue = Boolean(hidden);
|
|
550
|
+
}
|
|
551
|
+
|
|
552
|
+
if (!bypassState) {
|
|
553
|
+
this.hidden = newValue;
|
|
541
554
|
}
|
|
542
555
|
|
|
556
|
+
console.trace('electrobun toggle hidden: ', this.hidden, this.webviewId)
|
|
543
557
|
this.internalRpc.send.webviewTagSetHidden({
|
|
544
558
|
id: this.webviewId,
|
|
545
|
-
hidden: this.hidden
|
|
559
|
+
hidden: this.hidden|| Boolean(hidden),
|
|
546
560
|
});
|
|
547
561
|
}
|
|
548
562
|
}
|
|
@@ -124,12 +124,9 @@ export class BrowserView<T> {
|
|
|
124
124
|
this.ptr = this.init();
|
|
125
125
|
}
|
|
126
126
|
|
|
127
|
-
init() {
|
|
128
|
-
console.log('browserView init', this.id, this.windowId, this.renderer);
|
|
127
|
+
init() {
|
|
129
128
|
this.createStreams();
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
console.log('ffi createWEbview')
|
|
129
|
+
|
|
133
130
|
// TODO: add a then to this that fires an onReady event
|
|
134
131
|
return ffi.request.createWebview({
|
|
135
132
|
id: this.id,
|
|
@@ -162,8 +162,7 @@ export class BrowserWindow<T> {
|
|
|
162
162
|
|
|
163
163
|
}
|
|
164
164
|
|
|
165
|
-
get webview() {
|
|
166
|
-
console.log('getting webview for window: ', this.webviewId)
|
|
165
|
+
get webview() {
|
|
167
166
|
// todo (yoav): we don't want this to be undefined, so maybe we should just
|
|
168
167
|
// link directly to the browserview object instead of a getter
|
|
169
168
|
return BrowserView.getById(this.webviewId) as BrowserView<T>;
|
|
@@ -25,17 +25,21 @@ export class Tray {
|
|
|
25
25
|
template = true,
|
|
26
26
|
width = 16,
|
|
27
27
|
height = 16,
|
|
28
|
-
}: ConstructorOptions = {}) {
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
})
|
|
28
|
+
}: ConstructorOptions = {}) {
|
|
29
|
+
try {
|
|
30
|
+
this.ptr = ffi.request.createTray({
|
|
31
|
+
id: this.id,
|
|
32
|
+
title,
|
|
33
|
+
image: this.resolveImagePath(image),
|
|
34
|
+
template,
|
|
35
|
+
width,
|
|
36
|
+
height,
|
|
37
|
+
});
|
|
38
|
+
} catch (error) {
|
|
39
|
+
console.warn('Tray creation failed:', error);
|
|
40
|
+
console.warn('System tray functionality may not be available on this platform');
|
|
41
|
+
this.ptr = null;
|
|
42
|
+
}
|
|
39
43
|
|
|
40
44
|
TrayMap[this.id] = this;
|
|
41
45
|
}
|
|
@@ -50,10 +54,12 @@ export class Tray {
|
|
|
50
54
|
}
|
|
51
55
|
|
|
52
56
|
setTitle(title: string) {
|
|
57
|
+
if (!this.ptr) return;
|
|
53
58
|
ffi.request.setTrayTitle({ id: this.id, title });
|
|
54
59
|
}
|
|
55
60
|
|
|
56
61
|
setImage(imgPath: string) {
|
|
62
|
+
if (!this.ptr) return;
|
|
57
63
|
ffi.request.setTrayImage({
|
|
58
64
|
id: this.id,
|
|
59
65
|
image: this.resolveImagePath(imgPath),
|
|
@@ -61,6 +67,7 @@ export class Tray {
|
|
|
61
67
|
}
|
|
62
68
|
|
|
63
69
|
setMenu(menu: Array<MenuItemConfig>) {
|
|
70
|
+
if (!this.ptr) return;
|
|
64
71
|
const menuWithDefaults = menuConfigWithDefaults(menu);
|
|
65
72
|
ffi.request.setTrayMenu({
|
|
66
73
|
id: this.id,
|
|
@@ -75,7 +82,9 @@ export class Tray {
|
|
|
75
82
|
|
|
76
83
|
remove() {
|
|
77
84
|
console.log('Tray.remove() called for id:', this.id);
|
|
78
|
-
|
|
85
|
+
if (this.ptr) {
|
|
86
|
+
ffi.request.removeTray({ id: this.id });
|
|
87
|
+
}
|
|
79
88
|
delete TrayMap[this.id];
|
|
80
89
|
console.log('Tray removed from TrayMap');
|
|
81
90
|
}
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { ffi } from "../proc/native";
|
|
1
|
+
import { ffi, native } from "../proc/native";
|
|
2
2
|
|
|
3
3
|
// TODO: move this to a more appropriate namespace
|
|
4
4
|
export const moveToTrash = (path: string) => {
|
|
@@ -9,6 +9,11 @@ export const showItemInFolder = (path: string) => {
|
|
|
9
9
|
return ffi.request.showItemInFolder({ path });
|
|
10
10
|
};
|
|
11
11
|
|
|
12
|
+
export const quit = () => {
|
|
13
|
+
// Use native killApp for graceful shutdown
|
|
14
|
+
native.symbols.killApp();
|
|
15
|
+
};
|
|
16
|
+
|
|
12
17
|
export const openFileDialog = async (
|
|
13
18
|
opts: {
|
|
14
19
|
startingFolder?: string;
|
|
@@ -526,8 +526,7 @@ export const ffi = {
|
|
|
526
526
|
// init (like views://myview/index.html) so fast while the Bun FFI to load a url is still executing
|
|
527
527
|
// or something where the JSCallback that this postMessage fires is not available or busy or
|
|
528
528
|
// its memory is allocated to something else or something and the handler receives garbage data in Bun.
|
|
529
|
-
setTimeout(() => {
|
|
530
|
-
console.log('emitWebviewEvent', eventName, detail)
|
|
529
|
+
setTimeout(() => {
|
|
531
530
|
window.__electrobunInternalBridge?.postMessage(JSON.stringify({id: 'webviewEvent', type: 'message', payload: {id: window.__electrobunWebviewId, eventName, detail}}));
|
|
532
531
|
});
|
|
533
532
|
};
|
|
@@ -683,7 +682,7 @@ export const ffi = {
|
|
|
683
682
|
} = params;
|
|
684
683
|
|
|
685
684
|
const tray = Tray.getById(id);
|
|
686
|
-
|
|
685
|
+
|
|
687
686
|
native.symbols.setTrayMenu(
|
|
688
687
|
tray.ptr,
|
|
689
688
|
toCString(menuConfig)
|
|
@@ -691,18 +690,14 @@ export const ffi = {
|
|
|
691
690
|
},
|
|
692
691
|
|
|
693
692
|
removeTray: (params: { id: number }): void => {
|
|
694
|
-
const { id } = params;
|
|
695
|
-
|
|
696
|
-
const tray = Tray.getById(id);
|
|
697
|
-
console.log('Found tray:', tray);
|
|
693
|
+
const { id } = params;
|
|
694
|
+
const tray = Tray.getById(id);
|
|
698
695
|
|
|
699
696
|
if (!tray) {
|
|
700
697
|
throw `Can't remove tray. Tray no longer exists`;
|
|
701
698
|
}
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
native.symbols.removeTray(tray.ptr);
|
|
705
|
-
console.log('Native removeTray called successfully');
|
|
699
|
+
|
|
700
|
+
native.symbols.removeTray(tray.ptr);
|
|
706
701
|
// The Tray class will handle removing from TrayMap
|
|
707
702
|
},
|
|
708
703
|
setApplicationMenu: (params: {menuConfig: string}): void => {
|
|
@@ -900,7 +895,7 @@ native.symbols.setJSUtils(getMimeType, getHTMLForWebviewSync);
|
|
|
900
895
|
|
|
901
896
|
// TODO XX: revisit this as integrated into the will-navigate handler
|
|
902
897
|
const webviewDecideNavigation = new JSCallback((webviewId, url) => {
|
|
903
|
-
console.log('webviewDecideNavigation', webviewId, new CString(url))
|
|
898
|
+
console.log('TODO: webviewDecideNavigation', webviewId, new CString(url))
|
|
904
899
|
return true;
|
|
905
900
|
}, {
|
|
906
901
|
args: [FFIType.u32, FFIType.cstring],
|
|
@@ -1056,10 +1051,13 @@ const internalBridgeHandler = new JSCallback((id, msg) => {
|
|
|
1056
1051
|
threadsafe: true
|
|
1057
1052
|
});
|
|
1058
1053
|
|
|
1059
|
-
const trayItemHandler = new JSCallback((id, action) => {
|
|
1054
|
+
const trayItemHandler = new JSCallback((id, action) => {
|
|
1055
|
+
// Note: Some invisible character that doesn't appear in .length
|
|
1056
|
+
// is causing issues
|
|
1057
|
+
const actionString = (new CString(action).toString() || "").trim();
|
|
1060
1058
|
const event = electrobunEventEmitter.events.tray.trayClicked({
|
|
1061
1059
|
id,
|
|
1062
|
-
action:
|
|
1060
|
+
action: actionString,
|
|
1063
1061
|
});
|
|
1064
1062
|
|
|
1065
1063
|
let result;
|
|
@@ -1171,7 +1169,7 @@ export const internalRpcHandlers = {
|
|
|
1171
1169
|
return native.symbols.webviewCanGoForward(webviewPtr);
|
|
1172
1170
|
},
|
|
1173
1171
|
webviewTagCallAsyncJavaScript: (params) => {
|
|
1174
|
-
console.log('
|
|
1172
|
+
console.log('TODO: webviewTagCallAsyncJavaScript NOT YET IMPLEMENTED', params)
|
|
1175
1173
|
// Not implemented - users can use RPC for JavaScript execution if needed
|
|
1176
1174
|
}
|
|
1177
1175
|
},
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "electrobun",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.7",
|
|
4
4
|
"description": "Build ultra fast, tiny, and cross-platform desktop apps with Typescript.",
|
|
5
5
|
"license": "MIT",
|
|
6
6
|
"author": "Blackboard Technologies Inc.",
|
|
@@ -33,7 +33,8 @@
|
|
|
33
33
|
"build:release": "bun build.ts --release",
|
|
34
34
|
"dev:playground": "bun build:dev && bun build:cli && cd playground && npm install && bun build:dev && bun start",
|
|
35
35
|
"dev:playground:linux": "bun build:dev && npm link && cd playground && npm link electrobun && bun build:dev && bun start",
|
|
36
|
-
"dev:playground:clean": "cd playground && rm -rf node_modules && npm install && cd .. && bun dev:playground",
|
|
36
|
+
"dev:playground:clean": "cd playground && rm -rf node_modules && rm -rf vendors/cef && npm install && cd .. && bun dev:playground",
|
|
37
|
+
"dev:playground:clean:linux": "cd playground && rm -rf node_modules && rm -rf vendors/cef && npm install && cd .. && bun dev:playground:linux",
|
|
37
38
|
"dev:playground:rerun": "cd playground && bun start",
|
|
38
39
|
"dev:playground:canary": "bun build:release && cd playground && npm install && bun build:canary && bun start:canary",
|
|
39
40
|
"run:playground": "bun build:dev && bun build:cli && cd templates/interactive-playground && npm install && bun build:dev && bun start",
|