Compare commits
378 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4d0abeb37c |
||
|
|
033650d792 |
||
|
|
4c49f27edf |
||
|
|
c84578721c |
||
|
|
354fee648e |
||
|
|
da3ce17161 |
||
|
|
bbd1b33122 |
||
|
|
ae40ca4ac1 |
||
|
|
093aa2d663 |
||
|
|
e906751c89 |
||
|
|
718fd92f85 |
||
|
|
01b661f6a5 |
||
|
|
896344eb66 |
||
|
|
8fd0340404 |
||
|
|
bc4ee373b5 | ||
|
|
5d39f1aa9a | ||
|
|
a27995940a |
||
|
|
4e8b705cda |
||
|
|
7ee2b2d856 |
||
|
|
696c55c6ee |
||
|
|
0357730294 |
||
|
|
158fd41a8b |
||
|
|
fc2b7309c1 |
||
|
|
18b3d0587f |
||
|
|
60d148e4b1 |
||
|
|
423f7e4498 |
||
|
|
4dbde817f4 |
||
|
|
95689bdeb7 |
||
|
|
7d4fe64352 |
||
|
|
e27e85aae9 | ||
|
|
dd7094e5d3 | ||
|
|
6630fa5647 |
||
|
|
7957d23c25 |
||
|
|
b25fe7496f |
||
|
|
00b0ce936d |
||
|
|
bc62140ac0 |
||
|
|
ebe8de8d2b |
||
|
|
6a2619880c |
||
|
|
db11f350cd |
||
|
|
216c9961a5 |
||
|
|
764f9bb175 |
||
|
|
23bd70e057 |
||
|
|
a0cb86ebff |
||
|
|
7aaa203c5f |
||
|
|
44a9d617e8 |
||
|
|
8e77d9358e |
||
|
|
7b8355a385 |
||
|
|
cb3305a2fc |
||
|
|
c73b2dd753 |
||
|
|
e37a7b9d4b |
||
|
|
ef7d3301c9 |
||
|
|
d16fd500df |
||
|
|
27afad59f6 |
||
|
|
4f71b22665 |
||
|
|
467f70ada7 |
||
|
|
9578b627fd |
||
|
|
4c464b3092 |
||
|
|
ba2c9989e6 |
||
|
|
9f3b00bed9 |
||
|
|
e0e96c3bf8 |
||
|
|
9125ef64be |
||
|
|
e5deb1611e |
||
|
|
8d73bec252 |
||
|
|
17bb94bbbf |
||
|
|
ac867f6587 | ||
|
|
cb1c2d86c0 | ||
|
|
8513b77fd8 | ||
|
|
9c78746441 | ||
|
|
7a383e080f | ||
|
|
9df647bb99 |
||
|
|
fc1c90e0ce |
||
|
|
385f1dafb9 |
||
|
|
70d2d52be4 |
||
|
|
6e9b6a1ee5 |
||
|
|
366e6afa3f |
||
|
|
de7a04b57a |
||
|
|
322088d3f8 |
||
|
|
f01afbc852 |
||
|
|
4df077f9b2 |
||
|
|
db22cb234d |
||
|
|
152ac2a7ce |
||
|
|
c113a068ad |
||
|
|
6943a56e8f |
||
|
|
909c16c517 | ||
|
|
5ee47ccf7b |
||
|
|
dfff549002 |
||
|
|
855dcadd79 | ||
|
|
2b8276da42 | ||
|
|
a35b676e05 | ||
|
|
45167ff743 | ||
|
|
140a110e6d |
||
|
|
bc3299fff6 |
||
|
|
1589a2f835 |
||
|
|
fcaff5e09d |
||
|
|
b489af776c |
||
|
|
b7f2d4a43b | ||
|
|
0015f8d3cb |
||
|
|
857f7b7518 |
||
|
|
ac00787202 |
||
|
|
4d7b0b487c |
||
|
|
d258771151 |
||
|
|
8aa187b393 |
||
|
|
ebe377f375 |
||
|
|
62f0d7eb26 |
||
|
|
04e1b05d10 |
||
|
|
03412f9cb0 |
||
|
|
2c2fd26bb5 | ||
|
|
ce7b1fc62b |
||
|
|
91d5da6124 |
||
|
|
612e0853bf |
||
|
|
ae2d97543f |
||
|
|
0dc77a2893 |
||
|
|
559ff6e2f4 |
||
|
|
254a5a652e |
||
|
|
34517218f0 |
||
|
|
82b3420e53 |
||
|
|
b393cf03a3 |
||
|
|
43bfb094c2 |
||
|
|
6cbe626e7f |
||
|
|
e6b725b106 |
||
|
|
0282768c10 |
||
|
|
6544005892 |
||
|
|
ffd98d68da |
||
|
|
7002f2e943 |
||
|
|
72662cf05f | ||
|
|
d9f4a1883f | ||
|
|
7f3358d6a8 | ||
|
|
25f19e03c8 | ||
|
|
6486f9d9b2 | ||
|
|
3798b74c7e | ||
|
|
8b5fb90dae | ||
|
|
3f925105cb | ||
|
|
03758a01e3 | ||
|
|
dbcf85c50c | ||
|
|
c9392806ac | ||
|
|
a8a1f362cb | ||
|
|
82d958747a | ||
|
|
3b59c3f3b9 | ||
|
|
73ade6e94f | ||
|
|
ae8171e9fe | ||
|
|
9640e16c12 | ||
|
|
36a1f7b52b | ||
|
|
d2d9acbdf6 | ||
|
|
b987c1b413 |
||
|
|
1ec3708f68 |
||
|
|
a0937fd3ef |
||
|
|
e753157ad2 |
||
|
|
6b35e06780 | ||
|
|
01be6e3d1f |
||
|
|
466719d160 | ||
|
|
095e8be923 |
||
|
|
4597d7fa64 |
||
|
|
136273503e |
||
|
|
ca3e4f6c45 |
||
|
|
52515277a0 |
||
|
|
ae621d2883 |
||
|
|
832db6d10b |
||
|
|
be7608e079 |
||
|
|
e1282a6371 |
||
|
|
fd71325a42 |
||
|
|
bd8c88e8ac |
||
|
|
8e51d6d32f |
||
|
|
b3bb856ed1 |
||
|
|
2936e8b98e |
||
|
|
539effb6b5 |
||
|
|
d3d87d09aa |
||
|
|
c68c85a384 |
||
|
|
3248f2fd31 |
||
|
|
ac1479afa2 |
||
|
|
0c24aa4313 |
||
|
|
2bd3de1f7f |
||
|
|
0744756695 |
||
|
|
594e2bf60f |
||
|
|
151beed7e8 |
||
|
|
6af1028856 |
||
|
|
a93c52e182 |
||
|
|
49a4193887 |
||
|
|
1bc5a2758f |
||
|
|
0581290cfe |
||
|
|
105c10aee7 | ||
|
|
d1838f42bf |
||
|
|
30d7cccf50 |
||
|
|
19c8d98ed3 |
||
|
|
ce5f733457 | ||
|
|
312146c70e | ||
|
|
4788263b9a |
||
|
|
a220d53a91 |
||
|
|
de29a0bd6f |
||
|
|
467bbfc4e5 |
||
|
|
741ff242f7 |
||
|
|
83ec246f63 |
||
|
|
af659850fc |
||
|
|
9a10be69ae |
||
|
|
797016d736 |
||
|
|
fc1cf90574 | ||
|
|
b12dcb054b | ||
|
|
f8998da78d |
||
|
|
bc7b816c37 |
||
|
|
194b0586ba |
||
|
|
2f389d99a8 |
||
|
|
5b1caf0d08 |
||
|
|
8dc509f49b |
||
|
|
3930f58203 |
||
|
|
ba9ab72893 |
||
|
|
27c9737ecd |
||
|
|
f9392e9980 |
||
|
|
6ac0bcdf7f | ||
|
|
125c4ab485 |
||
|
|
92a25c7dfd | ||
|
|
dadf638c00 |
||
|
|
e7643b8605 | ||
|
|
9763cd3465 | ||
|
|
7245b5b4d7 |
||
|
|
2acf32cd36 |
||
|
|
9c7dc05cea |
||
|
|
59d8650a0f |
||
|
|
00e2f16971 |
||
|
|
993fde17fe |
||
|
|
ae5e3f47a7 | ||
|
|
6bf875f2a2 | ||
|
|
61876448f7 | ||
|
|
202eecdf94 |
||
|
|
ecf1c41db4 | ||
|
|
915efa06bb | ||
|
|
4541cf0b3a | ||
|
|
538ba8daac |
||
|
|
c2db2e550f |
||
|
|
ea2bfa9bcd |
||
|
|
d4015123dd |
||
|
|
ef73a75c68 |
||
|
|
2478926274 |
||
|
|
e9100152e7 |
||
|
|
5df9ac1a53 | ||
|
|
6a3ba3d613 |
||
|
|
15191c3bbe |
||
|
|
6b288be2fa | ||
|
|
5f233f9dd6 |
||
|
|
a78e8c95ee | ||
|
|
4228eab052 |
||
|
|
267e4ec9fa |
||
|
|
aee6d99702 |
||
|
|
dab09a94d7 |
||
|
|
6381e520b9 |
||
|
|
36743ca76f |
||
|
|
a04a31be8c | ||
|
|
114c15197b | ||
|
|
fa4bf38b12 |
||
|
|
7d66f3c26a |
||
|
|
dbf7bba69f |
||
|
|
b2f84d041c |
||
|
|
76f806fe82 |
||
|
|
76e41a6211 |
||
|
|
471a50cd04 |
||
|
|
cacbf030d6 |
||
|
|
49ff9b62bf |
||
|
|
f56093ae27 |
||
|
|
8519d8f024 |
||
|
|
54438a7644 |
||
|
|
7aba2c3b95 |
||
|
|
5be7ee74f8 |
||
|
|
f6aba688a9 |
||
|
|
8624da51f8 |
||
|
|
0d81cd2831 |
||
|
|
3224db508d |
||
|
|
1fb6403e7d |
||
|
|
ba01492198 |
||
|
|
7e45e3d025 |
||
|
|
49b524d169 |
||
|
|
bedebe0c06 |
||
|
|
536422d508 |
||
|
|
fa7c6d80a2 |
||
|
|
3605fdf42f |
||
|
|
347d8cf861 |
||
|
|
89db2ad082 | ||
|
|
8d1e5188ad | ||
|
|
f07ead3fb2 | ||
|
|
d04fd9a35f | ||
|
|
bed3ec4163 | ||
|
|
98f3cc845f |
||
|
|
74fa41330e | ||
|
|
4a1d101d04 |
||
|
|
d824318a66 |
||
|
|
00be6f24d2 |
||
|
|
55b90a50bc |
||
|
|
f82c971cb0 | ||
|
|
2aea5e2dae | ||
|
|
481c145cd3 |
||
|
|
51c7453bd2 |
||
|
|
4598af4d7a |
||
|
|
c4fdfd6415 |
||
|
|
d9b99a990d |
||
|
|
d6383364ab |
||
|
|
3a4c3e7a7f |
||
|
|
caf05adff3 |
||
|
|
67afec3c2a |
||
|
|
7566ed4ba6 |
||
|
|
90be707d9c |
||
|
|
82fd9de339 |
||
|
|
461d34c620 |
||
|
|
ee2156ee2c |
||
|
|
d730c963f4 |
||
|
|
fc0aea1038 |
||
|
|
e219e3b65e |
||
|
|
42e77506d9 |
||
|
|
896a90f69e |
||
|
|
c27d2ceb8e |
||
|
|
dd4aa56310 |
||
|
|
6345b64a22 |
||
|
|
2c45ae69bb |
||
|
|
dade880064 |
||
|
|
bd57598c03 |
||
|
|
8deb8a04e7 |
||
|
|
93b49391c7 |
||
|
|
e5be3c5cfe |
||
|
|
63e1f3c09c |
||
|
|
39c922bc9f |
||
|
|
cadbccfb72 |
||
|
|
ba38474050 |
||
|
|
86e3d51c8e |
||
|
|
10e3a13d12 |
||
|
|
5df8ecc961 |
||
|
|
dca2064916 |
||
|
|
13d4b218e7 |
||
|
|
d1ba26a043 |
||
|
|
1c163422aa |
||
|
|
bdb415130b |
||
|
|
e573bf4df9 |
||
|
|
9772523f46 |
||
|
|
157c8fdbc7 |
||
|
|
758a63648e |
||
|
|
f2881822d2 |
||
|
|
bb4e95e22d |
||
|
|
5ebccf1ea6 |
||
|
|
f08f4be868 | ||
|
|
a964be1ada |
||
|
|
f33e627360 |
||
|
|
1b6ed1bc00 |
||
|
|
14cc9ec45b |
||
|
|
26ff639b62 |
||
|
|
10abe246b0 |
||
|
|
8a5a0506bf |
||
|
|
a2e32fe414 |
||
|
|
7a5e41f904 |
||
|
|
5b8594928b |
||
|
|
a6288c414e |
||
|
|
bd2c1ea73f |
||
|
|
429e94f4ce |
||
|
|
f302c8053c |
||
|
|
5d2b4308a8 |
||
|
|
f4b21a6b37 |
||
|
|
265d2e45db |
||
|
|
c3a7266001 |
||
|
|
3721d73423 |
||
|
|
d218384396 |
||
|
|
475534c132 |
||
|
|
8e810d59f0 |
||
|
|
1a2310265f |
||
|
|
87b1325dbc |
||
|
|
f8c8611219 |
||
|
|
4b6a8e17c5 |
||
|
|
868931fe72 |
||
|
|
3f83b42db5 |
||
|
|
9995dae4ad |
||
|
|
d36d1718d9 |
||
|
|
0f61873fe8 |
||
|
|
fe1f23b0fd |
||
|
|
2b35861aee |
||
|
|
ddf27038e1 |
||
|
|
5b091db26d |
||
|
|
fe9495d776 |
||
|
|
7a40cc59ca |
||
|
|
e941f36267 |
||
|
|
482f19e6b9 |
||
|
|
dd6eb0fa75 |
||
|
|
9efaedfe39 |
||
|
|
c4c0d64fd5 |
||
|
|
ffcfa1b0e7 |
||
|
|
3204287f96 |
|
|
@ -1,7 +1,6 @@
|
|||
{
|
||||
"files": [
|
||||
"website/src/pages/credits.mdx",
|
||||
"docs/src/assets/contributors.html"
|
||||
"website/src/pages/credits.mdx"
|
||||
],
|
||||
"imageSize": 75,
|
||||
"commit": false,
|
||||
|
|
|
|||
|
|
@ -1,55 +0,0 @@
|
|||
{"id":"wails-webview2gtk6-0mc","title":"GTK4: Drag and drop not working - needs manual testing","description":"Native file drag-and-drop from file managers works in GTK3 but NOT in GTK4.\n\n**Symptoms:**\n- Dragging files onto GTK4 app causes WebKit to open file like a browser\n- GtkDropTarget signals (enter, leave, motion, drop) never fire\n- Debug logging shows no [DND-GTK4] messages during drag operations\n\n**Investigation Done:**\n- Added GtkDropControllerMotion with GTK_PHASE_CAPTURE for motion tracking\n- Added GtkDropTarget with GTK_PHASE_CAPTURE and accept handler for file drops\n- Both controllers added to WebKitWebView\n- WebKitGTK uses GtkDropTargetAsync internally in bubble phase\n\n**Key Finding:**\n- WebKitGTK 2.50.3 disabled file access (CVE-2025-13947) but this should not affect native GTK drops\n- Capture phase should run before WebKit's bubble phase handlers\n\n**Files Modified:**\n- v3/pkg/application/linux_cgo_gtk4.c - DND handlers with debug logging\n- v3/pkg/application/linux_cgo_gtk4.go - enableDND/disableDND\n\n**Testing Required:**\n1. Build: cd v3/examples/drag-n-drop \u0026\u0026 go build -a -o drag-n-drop-gtk4 .\n2. Run: ./drag-n-drop-gtk4\n3. Drag file from file manager to window\n4. Watch for [DND-GTK4] messages in console\n\n**If DropControllerMotion fires but GtkDropTarget doesn't:**\n- WebKit intercepts at lower level, may need GtkDropTargetAsync approach\n\n**If nothing fires:**\n- Issue with controller attachment to WebKitWebView","status":"closed","priority":1,"issue_type":"bug","created_at":"2026-01-08T15:26:58.12691099+11:00","updated_at":"2026-01-08T15:50:34.104083842+11:00","closed_at":"2026-01-08T15:50:34.104083842+11:00","close_reason":"Fixed - implemented GtkDropControllerMotion + GtkDropTarget with GTK_PHASE_CAPTURE"}
|
||||
{"id":"wails-webview2gtk6-588","title":"doctor-ng: New TUI doctor package","description":"","status":"closed","priority":1,"issue_type":"feature","created_at":"2026-01-06T15:53:57.74361022+11:00","updated_at":"2026-01-06T15:54:05.035250923+11:00","closed_at":"2026-01-06T15:54:05.035250923+11:00","close_reason":"Implemented: pkg/doctor-ng with modern bubbletea TUI, public API for GUI reuse, CLI command wails3 doctor-ng"}
|
||||
{"id":"wails-webview2gtk6-95s","title":"Window not found warning on application quit","description":"When quitting a systray application, a warning is logged: 'Window #1 not found'. This happens during cleanup when trying to access windows that have already been destroyed.\n\nReproduction:\n1. Run any systray test (e.g., custom-handlers-gtk4)\n2. Use the menu to quit\n3. Observe warning in console\n\nExpected: Clean shutdown without warnings\nActual: WRN Window #1 not found","status":"open","priority":2,"issue_type":"bug","created_at":"2026-01-06T14:35:05.897126324+11:00","updated_at":"2026-01-06T14:35:05.897126324+11:00"}
|
||||
{"id":"wails-webview2gtk6-e8m","title":"Cursor warps to window center on second systray click (Hyprland)","description":"On Hyprland, when using window-menu systray configuration:\n\n1. Click systray icon -\u003e window shows, cursor stays in place\n2. Click systray icon again -\u003e window hides then shows, cursor warps to window center\n\nThis only happens when toggling via systray icon click. Using menu 'Show Window' doesn't cause the warp.\n\nLikely related to PositionWindow() interaction with Hyprland's focus handling.\n\nEnvironment: Hyprland, GTK4\nPriority: Low (cosmetic issue)","status":"open","priority":3,"issue_type":"bug","created_at":"2026-01-06T14:49:45.489579343+11:00","updated_at":"2026-01-06T14:49:45.489579343+11:00"}
|
||||
{"id":"wails-webview2gtk6-m4c","title":"Systray API v2: Refactor for cleaner separation of concerns","description":"Redesign systray API for cleaner separation of concerns:\n\n## Core Principles\n1. Registration separate from behavior - AttachWindow/SetMenu only register resources\n2. Smart defaults with explicit overrides - Works out of the box, customizable when needed\n3. Window behavior belongs on window - HideOnFocusLost, HideOnEscape are window options\n4. Platform differences handled internally - User expresses intent, implementation adapts\n\n## Smart Defaults\n| Configuration | Left-Click | Right-Click |\n|--------------|------------|-------------|\n| Window only | ToggleWindow | Nothing |\n| Menu only | Nothing | ShowMenu |\n| Window + Menu | ToggleWindow | ShowMenu |\n\n## Scope\n- Window options: HideOnFocusLost, HideOnEscape\n- Systray smart defaults\n- GTK3 \u0026 GTK4 compatibility\n- Documentation, tests, examples","status":"closed","priority":1,"issue_type":"epic","created_at":"2026-01-06T12:41:49.962413423+11:00","updated_at":"2026-01-06T15:33:03.609804696+11:00","closed_at":"2026-01-06T15:33:03.609804696+11:00","close_reason":"All implementation tasks complete. Systray API v2 implemented with smart defaults, HideOnEscape, HideOnFocusLost, and comprehensive manual tests. GTK3/GTK4 verified."}
|
||||
{"id":"wails-webview2gtk6-m4c.1","title":"Add HideOnFocusLost window option","description":"Add HideOnFocusLost option to WebviewWindowOptions.\n\nFiles to modify:\n- webview_window_options.go: Add HideOnFocusLost bool field\n- webview_window.go: Implement focus-lost handler in setupBehaviorOptions()\n- linux_cgo.go: GTK3 focus-lost signal (focus-out-event)\n- linux_cgo_gtk4.go: GTK4 focus-lost signal (notify::is-active)\n- webview_window_darwin.go: macOS focus-lost handling\n- webview_window_windows.go: Windows focus-lost handling\n\nPlatform behavior:\n- Standard WMs: Hide on focus lost\n- Focus-follows-mouse WMs (Hyprland, Sway, i3): Silently disabled\n\nImplementation:\nif options.HideOnFocusLost {\n if runtime.GOOS == \"linux\" \u0026\u0026 isFocusFollowsMouse() {\n return // Skip - would cause immediate hide\n }\n w.OnWindowEvent(events.Common.WindowLostFocus, func(e *WindowEvent) {\n w.Hide()\n })\n}","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:42:15.123041365+11:00","updated_at":"2026-01-06T13:02:45.845914238+11:00","closed_at":"2026-01-06T13:02:45.845914238+11:00","close_reason":"Implemented HideOnFocusLost option","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.1","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:42:15.128286221+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.2","title":"Add HideOnEscape window option","description":"Add HideOnEscape option to WebviewWindowOptions.\n\nFiles to modify:\n- webview_window_options.go: Add HideOnEscape bool field\n- webview_window.go: Register Escape keybinding in setupBehaviorOptions()\n\nImplementation:\nif options.HideOnEscape {\n w.registerKeyBinding(\"escape\", func() {\n w.Hide()\n })\n}\n\nNotes:\n- Should work on all platforms (GTK3, GTK4, macOS, Windows)\n- Uses existing keybinding infrastructure","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:42:23.973789683+11:00","updated_at":"2026-01-06T13:02:46.561848535+11:00","closed_at":"2026-01-06T13:02:46.561848535+11:00","close_reason":"Implemented HideOnEscape option","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.2","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:42:23.978484152+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.3","title":"Implement systray smart defaults","description":"Implement smart defaults for systray click behavior.\n\nSmart Defaults:\n| Configuration | Left-Click | Right-Click |\n|--------------|------------|-------------|\n| Window only | ToggleWindow | Nothing |\n| Menu only | Nothing | ShowMenu |\n| Window + Menu | ToggleWindow | ShowMenu |\n| Neither | Nothing | Nothing |\n\nFiles to modify:\n- systemtray.go: Add applySmartDefaults() method, call from Run()\n\nImplementation:\nfunc (s *SystemTray) applySmartDefaults() {\n hasWindow := s.attachedWindow.Window != nil\n hasMenu := s.menu != nil\n \n if s.clickHandler == nil {\n if hasWindow {\n s.clickHandler = s.ToggleWindow\n }\n }\n \n if s.rightClickHandler == nil {\n if hasMenu {\n s.rightClickHandler = s.ShowMenu\n }\n }\n}\n\nUser-specified OnLeftClick/OnRightClick handlers override these defaults.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:42:34.796175422+11:00","updated_at":"2026-01-06T13:02:47.607457075+11:00","closed_at":"2026-01-06T13:02:47.607457075+11:00","close_reason":"Implemented smart defaults in applySmartDefaults()","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.3","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:42:34.801495751+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.4","title":"Fix Linux systray Activate/SecondaryActivate handlers","description":"Fix Linux systray DBus handlers to call correct click handlers.\n\nCurrent issues:\n- Activate calls doubleClickHandler instead of clickHandler\n- ItemIsMenu is always true, causing host to intercept left-click\n- Menu property registered even when no menu\n\nFiles to modify:\n- systemtray_linux.go\n\nChanges:\n1. Activate() should call s.parent.clickHandler (not doubleClickHandler)\n2. SecondaryActivate() should call s.parent.rightClickHandler\n3. ItemIsMenu = false when window attached (let our code handle clicks)\n4. Only register Menu property when s.menu != nil\n\nImplementation already partially done in this session - verify and clean up.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:42:47.726574187+11:00","updated_at":"2026-01-06T13:02:48.48112849+11:00","closed_at":"2026-01-06T13:02:48.48112849+11:00","close_reason":"Fixed Activate/SecondaryActivate handlers","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.4","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:42:47.731830675+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.5","title":"Add systray API v2 unit tests","description":"Add unit tests for new systray behavior.\n\nTest cases:\n- TestSystraySmartDefaults_WindowOnly: Left=toggle, Right=nothing\n- TestSystraySmartDefaults_MenuOnly: Left=nothing, Right=menu\n- TestSystraySmartDefaults_WindowAndMenu: Left=toggle, Right=menu\n- TestSystraySmartDefaults_Neither: Left=nothing, Right=nothing\n- TestSystrayOverride_LeftClick: Custom handler overrides default\n- TestSystrayOverride_RightClick: Custom handler overrides default\n- TestWindowOption_HideOnFocusLost: Window hides on focus lost\n- TestWindowOption_HideOnEscape: Window hides on Escape\n- TestWindowOption_FocusFollowsMouse: HideOnFocusLost disabled on tiling WMs\n\nFiles:\n- systemtray_test.go\n- webview_window_test.go","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T12:42:58.128530198+11:00","updated_at":"2026-01-06T12:42:58.128530198+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.5","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:42:58.133914168+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.6","title":"Update systray documentation","description":"Update documentation for new systray API.\n\nFiles to update:\n- mkdocs-website/docs/learn/systray.md: Full rewrite\n- mkdocs-website/docs/learn/windows.md: Document HideOnFocusLost, HideOnEscape\n- mkdocs-website/docs/api/systray.md: API reference\n\nDocumentation structure:\n1. Basic Usage\n - Window-based systray (popup)\n - Menu-based systray\n - Window + Menu\n2. Smart Defaults explanation\n3. Customizing Behavior\n - OnLeftClick/OnRightClick overrides\n4. Window auto-hide options\n - HideOnFocusLost\n - HideOnEscape\n - Platform considerations (focus-follows-mouse)\n5. Platform Notes (Linux, macOS, Windows)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-06T12:43:08.693794811+11:00","updated_at":"2026-01-06T12:43:08.693794811+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.6","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:43:08.699255848+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.7","title":"Update systray examples","description":"Update and create systray examples.\n\nUpdate:\n- examples/systray-basic/main.go: Show HideOnFocusLost, HideOnEscape options\n\nCreate:\n- examples/systray-menu/main.go: Menu-only example\n- examples/systray-window-menu/main.go: Window + Menu example\n\nEach example should demonstrate:\n- Minimal setup\n- Smart defaults in action\n- How to customize if needed\n\nExample for systray-basic:\nwindow := app.NewWindow(WebviewWindowOptions{\n Hidden: true,\n Frameless: true,\n AlwaysOnTop: true,\n HideOnFocusLost: true, // NEW\n HideOnEscape: true, // NEW\n})\nsystray.AttachWindow(window)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-06T12:43:19.315995474+11:00","updated_at":"2026-01-06T13:02:49.08857561+11:00","closed_at":"2026-01-06T13:02:49.08857561+11:00","close_reason":"Updated systray-basic example","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.7","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:43:19.323424534+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.8","title":"Verify GTK3 and GTK4 compatibility","description":"Verify all systray changes work on both GTK3 and GTK4.\n\nTest matrix:\n| Feature | GTK3 | GTK4 |\n|---------|------|------|\n| Left-click toggle window | Test | Test |\n| Right-click show menu | Test | Test |\n| HideOnFocusLost | Test | Test |\n| HideOnEscape | Test | Test |\n| ItemIsMenu property | Test | Test |\n| Menu property conditional | Test | Test |\n\nBuild commands:\n- GTK4: go build ./pkg/application/...\n- GTK3: go build -tags gtk3 ./pkg/application/...\n\nTest on:\n- Hyprland (tiling, focus-follows-mouse)\n- GNOME (standard WM)\n\nDocument any GTK3/GTK4 differences in behavior.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:43:30.274572191+11:00","updated_at":"2026-01-06T15:32:18.160668676+11:00","closed_at":"2026-01-06T15:32:18.160668676+11:00","close_reason":"Verified GTK3/GTK4 compatibility - all tests pass","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.8","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:43:30.279370657+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-m4c.9","title":"Clean up current session systray changes","description":"Clean up partial implementation from current session.\n\nChanges made in this session that need review/cleanup:\n1. systemtray_linux.go:\n - Activate() now calls clickHandler (correct)\n - SecondaryActivate() calls rightClickHandler or OpenMenu (correct)\n - ItemIsMenu conditional on window/menu presence (correct)\n - Menu property only registered when menu exists (correct)\n - Removed 'Open window' menu item injection (correct)\n\n2. environment_linux.go:\n - Added isTilingWM() helper (keep)\n - Removed unused Hyprland IPC functions (keep)\n - Cleaned up debug output (keep)\n\n3. linux_cgo.go / linux_cgo_gtk4.go:\n - Added setOpacity() - keep for future use\n\n4. webview_window_linux.go:\n - Removed unused compositorWindowID field (keep)\n\n5. examples/systray-basic/main.go:\n - Added Escape keybinding manually (will be replaced by HideOnEscape option)\n\nReview all changes, ensure they align with spec, commit clean state.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-06T12:43:44.358797107+11:00","updated_at":"2026-01-06T13:02:50.19506054+11:00","closed_at":"2026-01-06T13:02:50.19506054+11:00","close_reason":"Cleanup complete","dependencies":[{"issue_id":"wails-webview2gtk6-m4c.9","depends_on_id":"wails-webview2gtk6-m4c","type":"parent-child","created_at":"2026-01-06T12:43:44.36368827+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e","title":"WebKitGTK 6.0 / GTK4 Support for Wails v3","description":"Add WebKitGTK 6.0 (GTK4) support to Wails v3 as the DEFAULT target. GTK3/WebKit4.1 available via -tags gtk3 for legacy systems.\n\nArchitecture:\n- Default (no tag): GTK4 + WebKitGTK 6.0\n- Legacy (-tags gtk3): GTK3 + WebKit2GTK 4.1\n\nDocker container provides BOTH library sets for cross-compilation:\n- task build:linux → GTK4/WebKit6 (modern, default)\n- task build:linux:gtk3 → GTK3/WebKit4.1 (legacy backport)\n\nSame pattern as macOS/Windows cross-compilation from Linux.","status":"open","priority":1,"issue_type":"epic","created_at":"2026-01-04T12:06:52.983769501+11:00","updated_at":"2026-01-04T12:52:12.372486756+11:00"}
|
||||
{"id":"wails-webview2gtk6-t4e.1","title":"Phase 1: Add gtk3 build constraint to existing GTK3/WebKit4.1 files","description":"Rename/constrain existing GTK3 files to require -tags gtk3:\n- linux_cgo.go → add //go:build linux \u0026\u0026 gtk3\n- clipboard_linux.go → add //go:build linux \u0026\u0026 gtk3\n- menu_linux.go → add //go:build linux \u0026\u0026 gtk3\n- menuitem_linux.go → add //go:build linux \u0026\u0026 gtk3\n- screen_linux.go → add //go:build linux \u0026\u0026 gtk3\n- dialogs_linux.go → add //go:build linux \u0026\u0026 gtk3\n- webkit2.go → add //go:build linux \u0026\u0026 gtk3\n\nThese become the LEGACY path, only built with -tags gtk3","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:07:40.301322984+11:00","updated_at":"2026-01-06T15:34:36.338594373+11:00","closed_at":"2026-01-06T15:34:36.338594373+11:00","close_reason":"GTK3 files have gtk3 build tag","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.1","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:40.306919353+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.10","title":"Phase 4: Implement webkit6 asset server","description":"webkit6.go, request_linux_webkit6.go, responsewriter_linux_webkit6.go - URI scheme handling with WebKitGTK 6.0 API (webkit_uri_scheme_response_new).","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:08:08.383542838+11:00","updated_at":"2026-01-06T15:34:41.942498525+11:00","closed_at":"2026-01-06T15:34:41.942498525+11:00","close_reason":"WebKit6 asset server implemented - URI scheme handling works","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.10","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:08.389188642+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.11","title":"Phase 5: Implement GMenu/GAction menu system","description":"Complete rewrite from GtkMenu/GtkMenuItem to GMenu/GAction/GtkPopoverMenuBar. Most significant GTK4 change. Reference v2 PR #4570 menu_webkit6.go but fix race conditions.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:08:40.990519767+11:00","updated_at":"2026-01-06T20:27:18.582723928+11:00","closed_at":"2026-01-06T20:27:18.582723928+11:00","close_reason":"Completed - GMenu/GAction implemented in menu_linux_gtk4.go and linux_cgo_gtk4.c","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.11","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:40.995669687+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.12","title":"Phase 5: Implement menu item state handling","description":"GSimpleAction for text/checkbox/radio items. Stateful actions with g_simple_action_new_stateful. Proper checked state sync. Fix nil checks from v2 PR issues.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:08:45.52200628+11:00","updated_at":"2026-01-06T20:27:20.311243355+11:00","closed_at":"2026-01-06T20:27:20.311243355+11:00","close_reason":"Completed - GSimpleAction with stateful actions for checkbox/radio implemented","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.12","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:45.526654215+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.13","title":"Phase 5: Implement GTK4 keyboard accelerators","description":"gtk_application_set_accels_for_action for menu shortcuts. Map existing accelerator format to GTK4 format.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:08:49.061335186+11:00","updated_at":"2026-01-06T20:27:20.562596782+11:00","closed_at":"2026-01-06T20:27:20.562596782+11:00","close_reason":"Completed - gtk_application_set_accels_for_action() implemented in Phase 9","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.13","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:49.066422576+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.14","title":"Phase 6: Implement GTK4 clipboard API","description":"Replace gtk_clipboard_get with gdk_display_get_clipboard/gdk_display_get_primary_clipboard. Use GdkContentProvider for setting text.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:08:53.275247028+11:00","updated_at":"2026-01-06T20:27:22.183597579+11:00","closed_at":"2026-01-06T20:27:22.183597579+11:00","close_reason":"Completed - GdkClipboard implemented in linux_cgo_gtk4.go","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.14","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:53.279707286+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.15","title":"Phase 6: Implement GTK4 dialogs","description":"File chooser and message dialogs. Use deprecated-but-functional APIs (gtk_file_chooser_dialog_new deprecated 4.10 but works). Consider GtkFileDialog for future.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:08:59.838538142+11:00","updated_at":"2026-01-06T20:27:22.294219031+11:00","closed_at":"2026-01-06T20:27:22.294219031+11:00","close_reason":"Completed - GtkFileDialog and GtkAlertDialog implemented in Phase 8","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.15","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:59.843372832+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.16","title":"Phase 6: Implement GTK4 screen/monitor handling","description":"GdkMonitor/GdkDisplay GTK4 changes. Note: gdk_monitor_is_primary removed - handle gracefully or use alternative detection.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:09:08.402102924+11:00","updated_at":"2026-01-06T20:27:35.337382837+11:00","closed_at":"2026-01-06T20:27:35.337382837+11:00","close_reason":"N/A - GTK4 uses GdkDisplay/GdkMonitor which are mostly backwards compatible; no special handling needed","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.16","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:09:08.406691355+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.17","title":"Phase 6: Implement GTK4 event controllers","description":"Replace GTK3 signals with GTK4 event controllers: GtkGestureClick for button-press, GtkEventControllerKey for key events, GtkEventControllerMotion for motion.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:09:11.122143159+11:00","updated_at":"2026-01-06T20:27:23.251573875+11:00","closed_at":"2026-01-06T20:27:23.251573875+11:00","close_reason":"Completed - GtkEventControllerFocus/GtkGestureClick/GtkEventControllerKey implemented in Phase 3","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.17","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:09:11.127168452+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.18","title":"Phase 7: Create webkit6 test matrix","description":"Test on Ubuntu 24.04, Fedora 40+, Arch Linux. Both X11 and Wayland sessions. Verify window lifecycle, menus, dialogs, clipboard, asset serving.","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:09:14.440029393+11:00","updated_at":"2026-01-04T12:09:14.440029393+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.18","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:09:14.444560094+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.19","title":"Phase 7: Update UNRELEASED_CHANGELOG.md","description":"Document: webkit_6 build flag, auto-detection via capabilities command, Taskfile integration, known limitations (window positioning on Wayland).","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:09:17.821748561+11:00","updated_at":"2026-01-04T12:09:17.821748561+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.19","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:09:17.826107005+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.2","title":"Phase 1: Create GTK4/WebKit6 files as DEFAULT (no build tag)","description":"Create new GTK4/WebKit6 implementation files as the default (no tag required):\n- linux_cgo.go → //go:build linux \u0026\u0026 !gtk3 with pkg-config: gtk4 webkitgtk-6.0\n- clipboard_linux.go → //go:build linux \u0026\u0026 !gtk3\n- menu_linux.go → //go:build linux \u0026\u0026 !gtk3 (GMenu/GAction)\n- menuitem_linux.go → //go:build linux \u0026\u0026 !gtk3\n- screen_linux.go → //go:build linux \u0026\u0026 !gtk3\n- dialogs_linux.go → //go:build linux \u0026\u0026 !gtk3\n- webkit6.go → //go:build linux \u0026\u0026 !gtk3\n\nGTK4 is now the DEFAULT path, built without any tags","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:07:41.961703449+11:00","updated_at":"2026-01-06T15:34:38.035912813+11:00","closed_at":"2026-01-06T15:34:38.035912813+11:00","close_reason":"GTK4 files exist as default (linux_cgo_gtk4.go, menu_linux_gtk4.go, etc.)","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.2","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:41.966174608+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.20","title":"Phase 7: Write GTK4/WebKit6 documentation","description":"Migration guide covering: distro requirements, build flags, window positioning limitations, menu system changes, API differences from GTK3.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T12:09:20.269607376+11:00","updated_at":"2026-01-04T12:09:20.269607376+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.20","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:09:20.274078494+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.21","title":"Phase 8: V2 PR #4570 Fixes Tracker","description":"Track issues to backport to v2 PR after v3 port complete. Current known issues:\n- Race conditions: menu maps accessed without sync (menu_webkit6.go)\n- Nil checks missing: gActionIdToMenuItem.Load ignores ok bool (gtk_webkit6.go:18,22,34,45)\n- Memory leak: C.CString(title) not freed (window_webkit6.go:384)\n- Header mismatch: sendShowInspectorMessage signature wrong (window_webkit6.h:127)\n- Wrong cast: GtkWindow passed as GdkToplevel (window_webkit6.c:672,699)\n- Broken logic: IsMinimised returns wrong value (window_webkit6.c:383-387)\n- Incomplete: drag-drop just prints paths (window_webkit6.c:574-585)\n- Missing: separator handling in menus\nUPDATE THIS AS MORE ISSUES FOUND DURING V3 PORT","status":"open","priority":3,"issue_type":"task","created_at":"2026-01-04T12:09:35.71638895+11:00","updated_at":"2026-01-04T12:09:35.71638895+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.21","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:09:35.720786909+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.22","title":"Test Strategy: Build tag verification","description":"Verify build constraints work correctly:\n\nDefault build (no tags):\n- Uses GTK4/WebKitGTK 6.0 files\n- Compiles cleanly with gtk4 and webkitgtk-6.0 pkg-config\n\nLegacy build (-tags gtk3):\n- Uses GTK3/WebKit2GTK 4.1 files\n- Compiles cleanly with gtk+-3.0 and webkit2gtk-4.1 pkg-config\n\nVerify:\n- No file conflicts or duplicate symbols in either config\n- Both builds produce working binaries\n- CI matrix tests both configurations\n- Docker cross-compilation works for both targets","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:40:55.065828451+11:00","updated_at":"2026-01-04T12:53:15.945916832+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.22","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:40:55.071357519+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.23","title":"Test Strategy: GTK3 legacy build regression tests","description":"Ensure GTK3 legacy path (-tags gtk3) still works:\n- All existing Linux tests pass WITH -tags gtk3\n- Window lifecycle (create, show, hide, destroy)\n- Menu system (items, checkboxes, radio, separators, accelerators)\n- Dialogs (file open/save, message dialogs)\n- Clipboard operations\n- Asset serving via wails:// scheme\n- JavaScript execution and callbacks\n\nRun via Docker on systems without GTK3 dev libs locally.\nThis is the LEGACY path for older distros.","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:40:57.736554584+11:00","updated_at":"2026-01-04T12:53:21.402683536+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.23","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:40:57.74152021+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.24","title":"Test Strategy: GTK4 default build tests","description":"Verify GTK4 (default, no tags) works correctly:\n- Window lifecycle identical to GTK3 behavior\n- Menu system: GMenu/GAction produces same UX as GtkMenu\n- Dialogs: same file filters, default paths work\n- Clipboard: copy/paste text works identically \n- Asset serving: wails:// scheme works\n- JS execution: evaluate_javascript produces same results\n\nDocument intentional differences:\n- Window positioning is no-op on Wayland (expected)\n- Minor visual differences due to GTK4 theming","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:01.206249936+11:00","updated_at":"2026-01-04T12:53:26.644766099+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.24","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:01.21075179+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.25","title":"Test Strategy: Cross-distro matrix","description":"Test on multiple distributions:\n| Distro | GTK4/WebKit6 | GTK3/WebKit4.1 | Priority |\n|--------|--------------|----------------|----------|\n| Ubuntu 24.04 | ✓ test | ✓ test | HIGH |\n| Ubuntu 22.04 | N/A | ✓ test | HIGH |\n| Fedora 40+ | ✓ test | ✓ test | HIGH |\n| Arch Linux | ✓ test | ✓ test | MEDIUM |\n| Debian 12 | ✓ backports | ✓ test | MEDIUM |\n\nUse Docker containers or VMs for reproducible testing.","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:11.624965746+11:00","updated_at":"2026-01-04T12:41:11.624965746+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.25","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:11.62962541+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.26","title":"Test Strategy: X11 vs Wayland session testing","description":"Test both display servers:\nX11 Session:\n- Window positioning should work (GTK3) or no-op gracefully (GTK4)\n- All features functional\n- Performance baseline\n\nWayland Session:\n- Window positioning confirmed as no-op (expected)\n- No crashes or errors from positioning attempts\n- Native Wayland rendering (GTK4 benefits)\n- Verify GDK_BACKEND handling\n\nTest with: GDK_BACKEND=x11 and GDK_BACKEND=wayland","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:15.327289032+11:00","updated_at":"2026-01-04T12:41:15.327289032+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.26","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:15.331938707+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.27","title":"Test Strategy: Doctor and capabilities command tests","description":"Test tooling works correctly:\n- wails3 doctor shows GTK3/4 and WebKit4.1/6.0 availability\n- wails3 doctor only shows 'installed' for actual dev packages (not runtime)\n- wails3 capabilities --json returns correct structure\n- wails3 capabilities --linux-tags returns 'webkit_6' when available, empty when not\n- Taskfile integration works (auto-selects correct tags)\n- Test on system WITH gtk4/webkit6 dev packages\n- Test on system WITHOUT gtk4/webkit6 (only gtk3)","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:19.283226161+11:00","updated_at":"2026-01-04T12:41:19.283226161+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.27","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:19.287996887+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.28","title":"Test Strategy: Auto-detection fallback behavior","description":"Test the smart default behavior:\nScenario 1: System has GTK4 + WebKit6\n- capabilities recommends webkit_6\n- Taskfile uses webkit_6 automatically\n- Build succeeds with GTK4 features\n\nScenario 2: System has only GTK3 + WebKit4.1\n- capabilities recommends default (no tag)\n- Taskfile uses no extra tags\n- Build succeeds with GTK3\n\nScenario 3: Neither available\n- Doctor shows clear error\n- Install commands displayed per distro\n- Build fails with helpful message","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:22.845473972+11:00","updated_at":"2026-01-04T12:41:22.845473972+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.28","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:22.850043685+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.29","title":"Test Strategy: Docker test containers","description":"Update Docker containers to support both GTK versions:\n\nSingle container with both library sets:\n- Ubuntu 24.04 base (has both GTK3 and GTK4)\n- libgtk-4-dev + libwebkitgtk-6.0-dev (default)\n- libgtk-3-dev + libwebkit2gtk-4.1-dev (legacy)\n\nBuild script parameters:\n- docker run wails-linux ./build.sh # GTK4 default\n- docker run wails-linux ./build.sh --gtk3 # GTK3 legacy\n\nArchitecture variants:\n- Dockerfile.linux-x86_64 (amd64)\n- Dockerfile.linux-arm64 (aarch64)\n\nStore in v3/test/docker/ directory","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:52.701057271+11:00","updated_at":"2026-01-04T12:53:38.599341789+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.29","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:52.706373965+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.3","title":"Phase 2: Update wails doctor for GTK4 as default","description":"Update doctor to check for GTK4/WebKit6 as primary requirement:\n\nPrimary checks (required for default build):\n- pkg-config --exists gtk4\n- pkg-config --exists webkitgtk-6.0\n\nSecondary checks (for legacy builds):\n- pkg-config --exists gtk+-3.0\n- pkg-config --exists webkit2gtk-4.1\n\nOutput example:\n GTK4 (gtk4) ✓ 4.14.1 [required for default build]\n WebKitGTK 6.0 ✓ 2.44.1 [required for default build]\n GTK3 (gtk+-3.0) ✓ 3.24.38 [for -tags gtk3 builds]\n WebKit2GTK 4.1 ✓ 2.44.1 [for -tags gtk3 builds]\n\nIf GTK4 missing: suggest Docker build or install commands","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:07:43.111264576+11:00","updated_at":"2026-01-06T15:38:15.173987437+11:00","closed_at":"2026-01-06T15:38:15.173987437+11:00","close_reason":"Doctor already correctly shows GTK4 as primary and GTK3 as legacy. Verified output shows gtk4 4.20.3, webkitgtk-6.0 2.50.3 as required, gtk3/webkit2gtk marked (legacy) as optional.","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.3","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:43.11571264+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.30","title":"Test Strategy: Docker-based doctor/capabilities tests","description":"Test both GTK versions via Docker:\n\nTest matrix for Docker builds:\n| Command | Expected Result |\n|---------|-----------------|\n| task build:linux | GTK4/WebKit6 binary |\n| task build:linux:gtk3 | GTK3/WebKit4.1 binary |\n\nVerify in Docker container:\n- Default build links against libgtk-4.so, libwebkitgtk-6.0.so\n- GTK3 build links against libgtk-3.so, libwebkit2gtk-4.1.so\n\nCross-compilation test:\n- Build from macOS → Linux GTK4 (Docker)\n- Build from macOS → Linux GTK3 (Docker)\n- Build from Windows → Linux GTK4 (Docker)","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:41:56.664141365+11:00","updated_at":"2026-01-04T12:53:44.010563993+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.30","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:41:56.668983135+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.31","title":"Test Strategy: Docker-based build verification","description":"Verify Docker builds produce correct binaries:\n\nDefault (GTK4) builds:\n- docker run wails-linux ./build.sh\n- Binary requires libgtk-4, libwebkitgtk-6.0 at runtime\n- Runs on Ubuntu 22.04+, Fedora 38+, Arch, Debian 12+\n\nLegacy (GTK3) builds:\n- docker run wails-linux ./build.sh --gtk3\n- Binary requires libgtk-3, libwebkit2gtk-4.1 at runtime\n- Runs on older distros (Ubuntu 20.04, Debian 11, RHEL 8)\n\nTest both binaries actually run on target systems (not just compile)","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:42:00.581467132+11:00","updated_at":"2026-01-04T12:53:49.143142805+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.31","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:42:00.586144259+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.32","title":"Test Strategy: CI workflow for multi-distro testing","description":"Add GitHub Actions workflow for automated testing:\n\n.github/workflows/linux-webkit6-tests.yml:\n- Trigger on PRs touching v3/pkg/application/*linux*, v3/internal/doctor/*\n- Matrix strategy with Docker containers\n- Jobs:\n 1. Build verification (both tag configs)\n 2. Doctor command output validation\n 3. Capabilities command JSON validation\n \nCache Docker images for faster CI runs.\nFail CI if any distro/config combination breaks.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T12:42:04.299112575+11:00","updated_at":"2026-01-04T12:42:04.299112575+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.32","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:42:04.30363047+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.33","title":"Test Strategy: Unit tests for new Go code","description":"Add unit tests for new functionality:\n\n- capabilities command parsing and JSON output\n- pkg-config detection wrapper functions\n- Build tag detection logic\n- DevPackageInstalled() / DevPackageVersion() functions\n- Taskfile tag generation logic\n\nTests should be runnable without GTK installed (mock pkg-config calls).\nLocation: v3/internal/doctor/*_test.go, v3/cmd/wails3/*_test.go","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:42:59.917988736+11:00","updated_at":"2026-01-04T12:42:59.917988736+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.33","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:42:59.91880054+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.34","title":"Test Strategy: Edge cases and error handling","description":"Test edge cases for webkit_6 implementation:\n\nMenu edge cases:\n- Empty menu\n- Deeply nested submenus (5+ levels)\n- Menu items with special characters (unicode, \u0026, \u003c, \u003e)\n- Rapid menu updates\n- Menu with 100+ items\n\nWindow edge cases:\n- Multiple windows simultaneously\n- Window close during JS execution\n- Rapid show/hide cycles\n\nError handling:\n- Graceful handling when WebKit crashes\n- Clear error messages for missing dependencies\n- Proper cleanup on application exit","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T12:43:02.108202689+11:00","updated_at":"2026-01-04T12:43:02.108202689+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.34","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:43:02.114118944+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.35","title":"Test Strategy: Memory and resource leak testing","description":"Verify no memory leaks in webkit_6 implementation:\n\nCritical areas (from v2 PR issues):\n- C.CString allocations must be freed\n- GObject ref counting (g_object_unref calls)\n- Menu rebuilds don't leak\n- Window create/destroy cycles don't leak\n\nTesting approach:\n- Use valgrind or AddressSanitizer\n- Create/destroy 1000 windows, measure memory\n- Rebuild menus 1000 times, measure memory\n- Long-running test (1 hour) with periodic operations\n\nCompare memory behavior between GTK3 and GTK4 builds.","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T12:43:08.315395906+11:00","updated_at":"2026-01-04T12:43:08.315395906+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.35","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:43:08.320587181+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.36","title":"Test Strategy: Example apps verification","description":"Verify all v3 example apps work with webkit_6:\n\nTest each example in v3/examples/:\n- Build with default tags (GTK3)\n- Build with -tags webkit_6 (GTK4)\n- Run and verify functionality matches\n\nPriority examples:\n- plain (basic window)\n- menu (menu system)\n- dialogs (file/message dialogs)\n- clipboard (copy/paste)\n- events (window events)\n- binding (Go-JS bindings)\n\nDocument any examples that need webkit_6-specific adjustments.","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:43:12.575574602+11:00","updated_at":"2026-01-04T12:43:12.575574602+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.36","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:43:12.58115082+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.37","title":"Phase 2: Update Docker container with both GTK3 and GTK4 libraries","description":"Update Dockerfile.linux-x86_64 and Dockerfile.linux-arm64 to include BOTH library sets:\n\nRUN apt-get install -y \\\n # GTK4 + WebKitGTK 6.0 (default/modern)\n libgtk-4-dev \\\n libwebkitgtk-6.0-dev \\\n # GTK3 + WebKit2GTK 4.1 (legacy)\n libgtk-3-dev \\\n libwebkit2gtk-4.1-dev \\\n libayatana-appindicator3-dev\n\nUpdate build script to accept GTK version parameter:\n- build-linux.sh gtk4 → builds with no tags (default)\n- build-linux.sh gtk3 → builds with -tags gtk3\n\nThis enables cross-compilation to EITHER target from any platform.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:53:05.672476127+11:00","updated_at":"2026-01-06T20:27:23.926443978+11:00","closed_at":"2026-01-06T20:27:23.926443978+11:00","close_reason":"Completed - Docker containers updated in Phase 6","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.37","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:53:05.678037266+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.38","title":"Test Strategy: Comprehensive performance benchmark suite","description":"Create benchmark suite to measure GTK4/WebKit6 vs GTK3/WebKit4.1 performance.\n\nRENDERING BENCHMARKS:\n- Time to First Paint (TTFP): Measure ms from app start to first meaningful content\n- Time to Interactive (TTI): When app responds to user input\n- Frame rate during scroll: 60fps target, measure drops\n- Large DOM: Render 10,000 list items, measure time and FPS\n- DOM manipulation: Add/remove 1000 elements, measure time\n- CSS animations: Complex animations, measure frame consistency\n- Reflow/repaint: Measure layout thrashing scenarios\n\nBINDING BENCHMARKS:\n- Call latency: Round-trip time for Go function call from JS\n- Throughput: Calls per second (simple function)\n- Large payload: Transfer 1MB JSON Go→JS and JS→Go\n- Concurrent calls: 100 simultaneous binding calls\n- Callback performance: Go calling back into JS\n\nASSET SERVER BENCHMARKS:\n- Small file latency: Load 1KB file, measure ms\n- Large file throughput: Load 10MB file, measure MB/s\n- Many files: Load 100 small files sequentially\n- Parallel loading: Load 20 files simultaneously\n- Streaming: Video/audio streaming performance\n\nMEMORY BENCHMARKS:\n- Initial footprint: Memory after app start\n- After heavy ops: Memory after DOM/binding stress\n- Leak detection: Memory after 1000 window open/close cycles\n- Long-running: Memory growth over 1 hour of use\n\nOUTPUT FORMAT:\n- JSON results for CI integration\n- Markdown report for human review\n- Compare GTK4 vs GTK3 side-by-side\n\nIMPLEMENTATION:\n- Create v3/test/benchmarks/ directory\n- Benchmark app with standardized test pages\n- Go benchmark harness using testing.B\n- Browser performance APIs (performance.now(), PerformanceObserver)","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:54:15.661692112+11:00","updated_at":"2026-01-04T12:54:15.661692112+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.38","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:54:15.667316351+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.39","title":"Test Strategy: Create benchmark test application","description":"Create dedicated benchmark application in v3/test/benchmarks/app/\n\nFRONTEND (benchmark pages):\n1. rendering.html - DOM/CSS performance tests\n - Virtual scroll with 100,000 items\n - CSS grid with 1000 cells\n - Animation stress test (50 simultaneous)\n - Canvas 2D drawing benchmark\n \n2. bindings.html - Go\u003c-\u003eJS communication tests\n - Ping-pong latency measurement\n - Large data serialization\n - Concurrent call stress test\n - Event emission throughput\n\n3. assets.html - Asset server tests\n - Image gallery (100 images)\n - Large file download\n - Streaming video playback\n - WebSocket throughput (if applicable)\n\n4. memory.html - Memory profiling\n - Allocate/deallocate cycles\n - DOM node creation/destruction\n - Image loading/unloading\n\nBACKEND (Go harness):\n- BenchmarkService with standardized test methods\n- Metrics collection and reporting\n- Automated test runner\n- Results export (JSON, CSV, Markdown)\n\nCOMPARISON MODE:\n- Run same tests on GTK4 and GTK3 builds\n- Generate comparison report\n- Highlight improvements/regressions\n- Statistical significance testing (multiple runs)","status":"open","priority":1,"issue_type":"task","created_at":"2026-01-04T12:54:33.607772979+11:00","updated_at":"2026-01-04T12:54:33.607772979+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.39","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:54:33.612719138+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.4","title":"Phase 2: Update wails3 capabilities command","description":"Update capabilities command for GTK4-default architecture:\n\nOutput structure:\n{\n \"linux\": {\n \"gtk4\": true,\n \"gtk3\": true,\n \"webkitgtk_6_0\": true,\n \"webkit2gtk_4_1\": true,\n \"default_available\": true, // Can build without tags\n \"legacy_available\": true, // Can build with -tags gtk3\n \"recommended\": \"default\" // or \"legacy\" or \"docker\"\n }\n}\n\nIf GTK4 not available locally, recommend Docker build.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:07:44.735354235+11:00","updated_at":"2026-01-06T20:46:36.935228449+11:00","closed_at":"2026-01-06T20:46:36.935228449+11:00","close_reason":"Implemented wails3 tool capabilities command","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.4","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:44.739955792+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.40","title":"Test Strategy: CI benchmark regression tracking","description":"Add CI workflow to track performance over time:\n\nWORKFLOW (.github/workflows/benchmarks.yml):\n- Trigger: Weekly schedule + manual dispatch\n- Run benchmarks on both GTK4 and GTK3 builds\n- Store results as artifacts\n- Compare against baseline\n\nTRACKING:\n- Store historical benchmark data\n- Alert on \u003e10% regression\n- Track trends over releases\n- Generate performance dashboard\n\nBASELINE ESTABLISHMENT:\n- Run benchmarks before GTK4 migration (current GTK3)\n- This becomes the baseline for comparison\n- Document expected improvements from GTK4/WebKit6\n\nREPORTING:\n- Post results to PR comments (for benchmark PRs)\n- Update performance docs with latest numbers\n- Publish comparison: GTK4 vs GTK3 vs other frameworks (Electron, Tauri)","status":"open","priority":2,"issue_type":"task","created_at":"2026-01-04T12:54:39.84655827+11:00","updated_at":"2026-01-04T12:54:39.84655827+11:00","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.40","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:54:39.851364533+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.5","title":"Phase 2: Update Taskfile with build:linux and build:linux:gtk3","description":"Update Taskfile.yaml with Linux build targets:\n\ntask build:linux → Default GTK4/WebKit6 build\ntask build:linux:gtk3 → Legacy GTK3/WebKit4.1 build (uses -tags gtk3)\n\nBoth work via Docker for cross-compilation:\n- Docker container has BOTH library sets installed\n- Build script accepts target parameter\n\nExample usage:\n task build:linux # GTK4 native or Docker\n task build:linux:gtk3 # GTK3 via Docker (or native with -tags gtk3)","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:07:46.101012374+11:00","updated_at":"2026-01-06T20:27:33.971988614+11:00","closed_at":"2026-01-06T20:27:33.971988614+11:00","close_reason":"Completed - Taskfile updated with test:example:linux:gtk3 and docker targets in Phase 6","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.5","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:46.105510654+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.6","title":"Phase 3: Implement GTK4 application lifecycle","description":"linux_cgo_webkit6.go - GTK4 app init with gtk_application_new, g_application_run, proper signal handlers. No gtk_init needed in GTK4.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:07:56.71551144+11:00","updated_at":"2026-01-06T15:34:38.511762855+11:00","closed_at":"2026-01-06T15:34:38.511762855+11:00","close_reason":"GTK4 application lifecycle implemented in application_linux_gtk4.go","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.6","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:56.721263416+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.7","title":"Phase 3: Implement GTK4 window management","description":"Window creation with gtk_window_set_child (not gtk_container_add). Widgets visible by default (no show_all). Fullscreen/maximize/minimize state handling.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:07:59.625663163+11:00","updated_at":"2026-01-06T15:34:39.557173339+11:00","closed_at":"2026-01-06T15:34:39.557173339+11:00","close_reason":"GTK4 window management implemented in linux_cgo_gtk4.go","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.7","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:07:59.63049083+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.8","title":"Phase 3: Implement WebKitGTK 6.0 WebView integration","description":"Use webkit_web_view_evaluate_javascript (not run_javascript), WebKitNetworkSession for network, URI scheme handler registration with new API.","status":"closed","priority":1,"issue_type":"task","created_at":"2026-01-04T12:08:02.595646332+11:00","updated_at":"2026-01-06T15:34:40.794896929+11:00","closed_at":"2026-01-06T15:34:40.794896929+11:00","close_reason":"WebKitGTK 6.0 WebView integration implemented in linux_cgo_gtk4.go","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.8","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:02.601222032+11:00","created_by":"daemon"}]}
|
||||
{"id":"wails-webview2gtk6-t4e.9","title":"Phase 3: Window positioning as no-op for webkit_6","description":"SetPosition, Center, GetPosition return gracefully on GTK4/Wayland. gtk_window_move removed intentionally by GTK. Document as known limitation.","status":"closed","priority":2,"issue_type":"task","created_at":"2026-01-04T12:08:05.494126564+11:00","updated_at":"2026-01-06T20:27:32.813843908+11:00","closed_at":"2026-01-06T20:27:32.813843908+11:00","close_reason":"Completed - Window positioning documented as no-op on Wayland in Decision 3 of IMPLEMENTATION.md","dependencies":[{"issue_id":"wails-webview2gtk6-t4e.9","depends_on_id":"wails-webview2gtk6-t4e","type":"parent-child","created_at":"2026-01-04T12:08:05.498782524+11:00","created_by":"daemon"}]}
|
||||
|
|
@ -1,71 +0,0 @@
|
|||
language: en-US
|
||||
tone_instructions: ''
|
||||
early_access: false
|
||||
enable_free_tier: true
|
||||
reviews:
|
||||
profile: chill
|
||||
request_changes_workflow: false
|
||||
high_level_summary: true
|
||||
high_level_summary_placeholder: '@coderabbitai summary'
|
||||
auto_title_placeholder: '@coderabbitai'
|
||||
review_status: true
|
||||
poem: true
|
||||
collapse_walkthrough: false
|
||||
sequence_diagrams: true
|
||||
path_filters: []
|
||||
path_instructions: []
|
||||
abort_on_close: true
|
||||
auto_review:
|
||||
enabled: true
|
||||
auto_incremental_review: true
|
||||
ignore_title_keywords: []
|
||||
labels: []
|
||||
drafts: false
|
||||
base_branches: ['v3-alpha', 'master']
|
||||
tools:
|
||||
shellcheck:
|
||||
enabled: true
|
||||
ruff:
|
||||
enabled: true
|
||||
markdownlint:
|
||||
enabled: true
|
||||
github-checks:
|
||||
enabled: true
|
||||
timeout_ms: 90000
|
||||
languagetool:
|
||||
enabled: true
|
||||
enabled_only: false
|
||||
level: default
|
||||
biome:
|
||||
enabled: true
|
||||
hadolint:
|
||||
enabled: true
|
||||
swiftlint:
|
||||
enabled: true
|
||||
phpstan:
|
||||
enabled: true
|
||||
level: default
|
||||
golangci-lint:
|
||||
enabled: true
|
||||
yamllint:
|
||||
enabled: true
|
||||
gitleaks:
|
||||
enabled: true
|
||||
checkov:
|
||||
enabled: true
|
||||
detekt:
|
||||
enabled: true
|
||||
eslint:
|
||||
enabled: true
|
||||
chat:
|
||||
auto_reply: true
|
||||
knowledge_base:
|
||||
opt_out: false
|
||||
learnings:
|
||||
scope: auto
|
||||
issues:
|
||||
scope: auto
|
||||
jira:
|
||||
project_keys: []
|
||||
linear:
|
||||
team_keys: []
|
||||
3
.gitattributes
vendored
|
|
@ -1,3 +0,0 @@
|
|||
|
||||
# Use bd merge for beads JSONL files
|
||||
.beads/issues.jsonl merge=beads
|
||||
4
.github/ISSUE_TEMPLATE/bug_report.yml
vendored
|
|
@ -7,8 +7,6 @@ body:
|
|||
- type: markdown
|
||||
attributes:
|
||||
value: |
|
||||
***Please note: No bug reports are currently being accepted for Wails v3***
|
||||
***Please note: No bug reports are currently being accepted for Wails v3***
|
||||
***Please note: No bug reports are currently being accepted for Wails v3***
|
||||
Before submitting this issue, please do the following:
|
||||
- Do a web search for your error. This usually leads to a much better understanding of the issue.
|
||||
|
|
@ -72,7 +70,7 @@ body:
|
|||
validations:
|
||||
required: false
|
||||
- type: textarea
|
||||
id: systemetails
|
||||
id: systemdetails
|
||||
attributes:
|
||||
label: System Details
|
||||
description: Please add the output of `wails doctor`.
|
||||
|
|
|
|||
3
.github/pull_request_template.md
vendored
|
|
@ -6,7 +6,6 @@
|
|||
* YOUR PR MAY BE REJECTED IF IT DOES NOT FOLLOW THESE STEPS *
|
||||
*********************************************************************
|
||||
|
||||
- *DO NOT* submit bugs for a source install of v3, ONLY tagged versions, e.g. v3.0.0-alpha.11
|
||||
- *DO NOT* submit PRs for v3 alpha enhancements, unless you have opened a post on the discord channel.
|
||||
All enhancements must be discussed first.
|
||||
The feedback guide for v3 is here: https://v3alpha.wails.io/getting-started/feedback/
|
||||
|
|
@ -48,7 +47,7 @@ Please paste the output of `wails doctor`. If you are unable to run this command
|
|||
|
||||
# Checklist:
|
||||
|
||||
- [ ] I have updated `v3/UNRELEASED_CHANGELOG.md` with details of this PR
|
||||
- [ ] I have updated `website/src/pages/changelog.mdx` with details of this PR
|
||||
- [ ] My code follows the general coding style of this project
|
||||
- [ ] I have performed a self-review of my own code
|
||||
- [ ] I have commented my code, particularly in hard-to-understand areas
|
||||
|
|
|
|||
2
.github/workflows/auto-label-issues.yml
vendored
|
|
@ -3,7 +3,7 @@ name: Auto Label Issues
|
|||
on:
|
||||
issues:
|
||||
types: [opened, edited, reopened]
|
||||
pull_request_target:
|
||||
pull_request:
|
||||
types: [opened, edited, reopened, synchronize]
|
||||
|
||||
jobs:
|
||||
|
|
|
|||
373
.github/workflows/automated-releases.yml
vendored
|
|
@ -1,373 +0,0 @@
|
|||
name: Automated Nightly Releases
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
force_release:
|
||||
description: 'Force release even if no changes detected'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
dry_run:
|
||||
description: 'Run in dry-run mode (no actual releases)'
|
||||
required: false
|
||||
default: false
|
||||
type: boolean
|
||||
# schedule:
|
||||
# Run at 2 AM UTC every day - DISABLED for safety until ready
|
||||
# - cron: '0 2 * * *'
|
||||
|
||||
env:
|
||||
GO_VERSION: '1.24'
|
||||
|
||||
jobs:
|
||||
check-permissions:
|
||||
name: Check Release Permissions
|
||||
permissions: {}
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
authorized: ${{ steps.check.outputs.authorized }}
|
||||
steps:
|
||||
- name: Check if user is authorized for releases
|
||||
id: check
|
||||
run: |
|
||||
# Only allow specific users to trigger releases
|
||||
AUTHORIZED_USERS="leaanthony"
|
||||
|
||||
if [[ "$AUTHORIZED_USERS" == *"${{ github.actor }}"* ]]; then
|
||||
echo "✅ User ${{ github.actor }} is authorized for releases"
|
||||
echo "authorized=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "❌ User ${{ github.actor }} is not authorized for releases"
|
||||
echo "authorized=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
detect-v2-changes:
|
||||
name: Detect v2 Changes
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-permissions
|
||||
if: needs.check-permissions.outputs.authorized == 'true'
|
||||
outputs:
|
||||
has_changes: ${{ steps.changes.outputs.has_changes }}
|
||||
commits_since_last: ${{ steps.changes.outputs.commits_since_last }}
|
||||
last_release_tag: ${{ steps.changes.outputs.last_release_tag }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check for v2 changes since last release
|
||||
id: changes
|
||||
run: |
|
||||
echo "🔍 Checking for v2 changes since last release..."
|
||||
|
||||
# Find the last v2 release tag
|
||||
LAST_TAG=$(git tag -l "v2.*" --sort=-version:refname | head -n 1)
|
||||
if [ -z "$LAST_TAG" ]; then
|
||||
echo "No previous v2 tags found, assuming first release"
|
||||
LAST_TAG=$(git rev-list --max-parents=0 HEAD)
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "commits_since_last=999" >> $GITHUB_OUTPUT
|
||||
echo "last_release_tag=none" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Last v2 release tag: $LAST_TAG"
|
||||
echo "last_release_tag=$LAST_TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
# Count commits since last release affecting v2 or root files
|
||||
COMMITS_COUNT=$(git rev-list --count ${LAST_TAG}..HEAD -- v2/ website/ README.md CHANGELOG.md || echo "0")
|
||||
echo "Commits since last v2 release: $COMMITS_COUNT"
|
||||
echo "commits_since_last=$COMMITS_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
if [ "$COMMITS_COUNT" -gt 0 ] || [ "${{ github.event.inputs.force_release }}" == "true" ]; then
|
||||
echo "✅ Changes detected or forced release"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "ℹ️ No changes detected since last release"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
fi
|
||||
|
||||
detect-v3-changes:
|
||||
name: Detect v3-alpha Changes
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-permissions
|
||||
if: needs.check-permissions.outputs.authorized == 'true'
|
||||
outputs:
|
||||
has_changes: ${{ steps.changes.outputs.has_changes }}
|
||||
commits_since_last: ${{ steps.changes.outputs.commits_since_last }}
|
||||
last_release_tag: ${{ steps.changes.outputs.last_release_tag }}
|
||||
steps:
|
||||
- name: Checkout v3-alpha branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: v3-alpha
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Check for v3-alpha changes since last release
|
||||
id: changes
|
||||
run: |
|
||||
echo "🔍 Checking for v3-alpha changes since last release..."
|
||||
|
||||
# Find the last v3 alpha release tag
|
||||
LAST_TAG=$(git tag -l "v3.*-alpha.*" --sort=-version:refname | head -n 1)
|
||||
if [ -z "$LAST_TAG" ]; then
|
||||
echo "No previous v3-alpha tags found, assuming first release"
|
||||
LAST_TAG=$(git rev-list --max-parents=0 HEAD)
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "commits_since_last=999" >> $GITHUB_OUTPUT
|
||||
echo "last_release_tag=none" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "Last v3-alpha release tag: $LAST_TAG"
|
||||
echo "last_release_tag=$LAST_TAG" >> $GITHUB_OUTPUT
|
||||
|
||||
# Count commits since last release affecting v3 or docs
|
||||
COMMITS_COUNT=$(git rev-list --count ${LAST_TAG}..HEAD -- v3/ docs/ || echo "0")
|
||||
echo "Commits since last v3-alpha release: $COMMITS_COUNT"
|
||||
echo "commits_since_last=$COMMITS_COUNT" >> $GITHUB_OUTPUT
|
||||
|
||||
if [ "$COMMITS_COUNT" -gt 0 ] || [ "${{ github.event.inputs.force_release }}" == "true" ]; then
|
||||
echo "✅ Changes detected or forced release"
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "ℹ️ No changes detected since last release"
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
fi
|
||||
|
||||
release-v2:
|
||||
name: Create v2 Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-permissions, detect-v2-changes]
|
||||
if: |
|
||||
needs.check-permissions.outputs.authorized == 'true' &&
|
||||
needs.detect-v2-changes.outputs.has_changes == 'true'
|
||||
outputs:
|
||||
version: ${{ steps.release.outputs.version }}
|
||||
release_notes: ${{ steps.release.outputs.release_notes }}
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Run v2 release script and extract notes
|
||||
id: release
|
||||
run: |
|
||||
echo "🚀 Running v2 release script..."
|
||||
cd v2/tools/release
|
||||
|
||||
# Run release script and capture output
|
||||
RELEASE_OUTPUT=$(go run release.go 2>&1)
|
||||
echo "$RELEASE_OUTPUT"
|
||||
|
||||
# Extract version from output or version file
|
||||
NEW_VERSION=$(cat ../../cmd/wails/internal/version.txt)
|
||||
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract release notes from delimited output
|
||||
RELEASE_NOTES=$(echo "$RELEASE_OUTPUT" | sed -n '/=== RELEASE NOTES FOR/,/=== END RELEASE NOTES ===/p' | sed '1d;$d')
|
||||
|
||||
# Save release notes to file for multiline output
|
||||
echo "$RELEASE_NOTES" > ../../../release_notes_v2.md
|
||||
|
||||
# Set output (escape for GitHub Actions)
|
||||
{
|
||||
echo "release_notes<<EOF"
|
||||
echo "$RELEASE_NOTES"
|
||||
echo "EOF"
|
||||
} >> $GITHUB_OUTPUT
|
||||
|
||||
echo "✅ v2 release script completed - version: $NEW_VERSION"
|
||||
|
||||
- name: Create v2 git tag and release
|
||||
if: github.event.inputs.dry_run != 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ steps.release.outputs.version }}"
|
||||
echo "📝 Creating v2 release: $VERSION"
|
||||
|
||||
# Configure git
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Commit the changelog changes
|
||||
git add website/src/pages/changelog.mdx v2/cmd/wails/internal/version.txt
|
||||
git commit -m "chore: release $VERSION
|
||||
|
||||
Automated release created by GitHub Actions
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# Create and push tag
|
||||
git tag -a "$VERSION" -m "Release $VERSION"
|
||||
git push origin master
|
||||
git push origin "$VERSION"
|
||||
|
||||
# Create GitHub release with notes
|
||||
gh release create "$VERSION" \
|
||||
--title "Release $VERSION" \
|
||||
--notes-file release_notes_v2.md \
|
||||
--target master
|
||||
|
||||
- name: Log dry-run results for v2
|
||||
if: github.event.inputs.dry_run == 'true'
|
||||
run: |
|
||||
echo "🧪 DRY RUN - Would have created v2 release:"
|
||||
echo "Version: ${{ steps.release.outputs.version }}"
|
||||
echo "Release Notes:"
|
||||
cat release_notes_v2.md
|
||||
|
||||
release-v3:
|
||||
name: Create v3-alpha Release
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-permissions, detect-v3-changes]
|
||||
if: |
|
||||
needs.check-permissions.outputs.authorized == 'true' &&
|
||||
needs.detect-v3-changes.outputs.has_changes == 'true'
|
||||
outputs:
|
||||
version: ${{ steps.release.outputs.version }}
|
||||
release_notes: ${{ steps.release.outputs.release_notes }}
|
||||
steps:
|
||||
- name: Checkout v3-alpha branch
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: v3-alpha
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: ${{ env.GO_VERSION }}
|
||||
|
||||
- name: Run v3 release script and extract notes
|
||||
id: release
|
||||
run: |
|
||||
echo "🚀 Running v3-alpha release script..."
|
||||
cd v3/tasks/release
|
||||
|
||||
# Run release script and capture output
|
||||
RELEASE_OUTPUT=$(go run release.go 2>&1)
|
||||
echo "$RELEASE_OUTPUT"
|
||||
|
||||
# Extract version from output or version file
|
||||
NEW_VERSION=$(cat ../../internal/version/version.txt)
|
||||
echo "version=$NEW_VERSION" >> $GITHUB_OUTPUT
|
||||
|
||||
# Extract release notes from delimited output
|
||||
RELEASE_NOTES=$(echo "$RELEASE_OUTPUT" | sed -n '/=== RELEASE NOTES FOR/,/=== END RELEASE NOTES ===/p' | sed '1d;$d')
|
||||
|
||||
# Save release notes to file for multiline output
|
||||
echo "$RELEASE_NOTES" > ../../../release_notes_v3.md
|
||||
|
||||
# Set output (escape for GitHub Actions)
|
||||
{
|
||||
echo "release_notes<<EOF"
|
||||
echo "$RELEASE_NOTES"
|
||||
echo "EOF"
|
||||
} >> $GITHUB_OUTPUT
|
||||
|
||||
echo "✅ v3-alpha release script completed - version: $NEW_VERSION"
|
||||
|
||||
- name: Create v3-alpha git tag and release
|
||||
if: github.event.inputs.dry_run != 'true'
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
run: |
|
||||
VERSION="${{ steps.release.outputs.version }}"
|
||||
echo "📝 Creating v3-alpha release: $VERSION"
|
||||
|
||||
# Configure git
|
||||
git config user.name "github-actions[bot]"
|
||||
git config user.email "41898282+github-actions[bot]@users.noreply.github.com"
|
||||
|
||||
# Commit the changelog changes
|
||||
git add docs/src/content/docs/changelog.mdx v3/internal/version/version.txt
|
||||
git commit -m "chore: release $VERSION
|
||||
|
||||
Automated v3-alpha release created by GitHub Actions
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
# Create and push tag
|
||||
git tag -a "$VERSION" -m "Release $VERSION"
|
||||
git push origin v3-alpha
|
||||
git push origin "$VERSION"
|
||||
|
||||
# Create GitHub release with notes
|
||||
gh release create "$VERSION" \
|
||||
--title "Release $VERSION" \
|
||||
--notes-file release_notes_v3.md \
|
||||
--target v3-alpha \
|
||||
--prerelease
|
||||
|
||||
- name: Log dry-run results for v3-alpha
|
||||
if: github.event.inputs.dry_run == 'true'
|
||||
run: |
|
||||
echo "🧪 DRY RUN - Would have created v3-alpha release:"
|
||||
echo "Version: ${{ steps.release.outputs.version }}"
|
||||
echo "Release Notes:"
|
||||
cat release_notes_v3.md
|
||||
|
||||
summary:
|
||||
name: Release Summary
|
||||
runs-on: ubuntu-latest
|
||||
needs: [check-permissions, detect-v2-changes, detect-v3-changes, release-v2, release-v3]
|
||||
if: always() && needs.check-permissions.outputs.authorized == 'true'
|
||||
steps:
|
||||
- name: Create release summary
|
||||
run: |
|
||||
echo "# 🚀 Automated Release Summary" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Repository**: ${{ github.repository }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Triggered by**: ${{ github.actor }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "**Dry Run Mode**: ${{ github.event.inputs.dry_run || 'false' }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# v2 Summary
|
||||
echo "## v2 Release" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${{ needs.detect-v2-changes.outputs.has_changes }}" == "true" ]; then
|
||||
if [ "${{ needs.release-v2.result }}" == "success" ]; then
|
||||
echo "✅ **v2 Release**: Created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo " - Version: ${{ needs.release-v2.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo " - Commits since last: ${{ needs.detect-v2-changes.outputs.commits_since_last }}" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **v2 Release**: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "⏭️ **v2 Release**: Skipped (no changes)" >> $GITHUB_STEP_SUMMARY
|
||||
echo " - Commits since last: ${{ needs.detect-v2-changes.outputs.commits_since_last }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
# v3 Summary
|
||||
echo "## v3-alpha Release" >> $GITHUB_STEP_SUMMARY
|
||||
if [ "${{ needs.detect-v3-changes.outputs.has_changes }}" == "true" ]; then
|
||||
if [ "${{ needs.release-v3.result }}" == "success" ]; then
|
||||
echo "✅ **v3-alpha Release**: Created successfully" >> $GITHUB_STEP_SUMMARY
|
||||
echo " - Version: ${{ needs.release-v3.outputs.version }}" >> $GITHUB_STEP_SUMMARY
|
||||
echo " - Commits since last: ${{ needs.detect-v3-changes.outputs.commits_since_last }}" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **v3-alpha Release**: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
else
|
||||
echo "⏭️ **v3-alpha Release**: Skipped (no changes)" >> $GITHUB_STEP_SUMMARY
|
||||
echo " - Commits since last: ${{ needs.detect-v3-changes.outputs.commits_since_last }}" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "---" >> $GITHUB_STEP_SUMMARY
|
||||
echo "🤖 **Automated Release System** | Generated with [Claude Code](https://claude.ai/code)" >> $GITHUB_STEP_SUMMARY
|
||||
266
.github/workflows/build-and-test-v3.yml
vendored
|
|
@ -5,6 +5,8 @@ on:
|
|||
types: [opened, synchronize, reopened, ready_for_review]
|
||||
branches:
|
||||
- v3-alpha
|
||||
paths:
|
||||
- 'v3/**'
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
branches:
|
||||
|
|
@ -27,6 +29,70 @@ jobs:
|
|||
echo "approved=false" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
test_go:
|
||||
name: Run Go Tests v3
|
||||
needs: check_approval
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: github.base_ref == 'v3-alpha'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
go-version: [1.24]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install linux dependencies
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config xvfb x11-xserver-utils at-spi2-core xdg-desktop-portal-gtk
|
||||
version: 1.0
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
cache-dependency-path: "v3/go.sum"
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Build Examples
|
||||
working-directory: v3
|
||||
run: task test:examples
|
||||
|
||||
- name: Run tests (mac)
|
||||
if: matrix.os == 'macos-latest'
|
||||
env:
|
||||
CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13
|
||||
working-directory: v3
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Run tests (windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
working-directory: v3
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Run tests (ubuntu)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
working-directory: v3
|
||||
run: >
|
||||
xvfb-run --auto-servernum
|
||||
sh -c '
|
||||
dbus-update-activation-environment --systemd --all &&
|
||||
go test -v ./...
|
||||
'
|
||||
|
||||
- name: Typecheck binding generator output
|
||||
working-directory: v3
|
||||
run: task generator:test:check
|
||||
|
||||
test_js:
|
||||
name: Run JS Tests
|
||||
needs: check_approval
|
||||
|
|
@ -45,172 +111,17 @@ jobs:
|
|||
with:
|
||||
node-version: ${{ matrix.node-version }}
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: |
|
||||
npm ci
|
||||
npx --yes esbuild@latest --version
|
||||
run: npm install
|
||||
working-directory: v2/internal/frontend/runtime
|
||||
|
||||
- name: Clean build artifacts
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: npm run clean
|
||||
|
||||
- name: Type-check runtime
|
||||
working-directory: v3
|
||||
run: task runtime:check
|
||||
|
||||
- name: Test runtime
|
||||
working-directory: v3
|
||||
run: task runtime:test
|
||||
|
||||
- name: Check that the bundled runtime builds
|
||||
working-directory: v3
|
||||
run: task runtime:build
|
||||
|
||||
- name: Check that the npm package builds
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: npm run build
|
||||
|
||||
- name: Pack runtime for template tests
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: npm pack
|
||||
|
||||
- name: Store runtime build artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: runtime-build-artifacts
|
||||
path: |
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/dist/
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/types/
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/tsconfig.tsbuildinfo
|
||||
|
||||
- name: Store runtime package
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: runtime-package
|
||||
path: v3/internal/runtime/desktop/@wailsio/runtime/*.tgz
|
||||
|
||||
test_go:
|
||||
name: Run Go Tests v3
|
||||
needs: [check_approval, test_js]
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: github.base_ref == 'v3-alpha'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
os: [windows-latest, ubuntu-latest, macos-latest]
|
||||
go-version: [1.24]
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install linux dependencies (GTK3)
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config xvfb x11-xserver-utils at-spi2-core xdg-desktop-portal-gtk
|
||||
version: 1.0
|
||||
|
||||
- name: Install linux dependencies (GTK4)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-4-dev libwebkitgtk-6.0-dev
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
cache: true
|
||||
cache-dependency-path: "v3/go.sum"
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Retrieve runtime build artifacts
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: runtime-build-artifacts
|
||||
path: v3/internal/runtime/desktop/@wailsio/runtime/
|
||||
|
||||
- name: Build Examples (GTK3 default)
|
||||
working-directory: v3
|
||||
run: |
|
||||
echo "Starting example compilation tests (GTK3)..."
|
||||
task test:examples
|
||||
echo "Example compilation tests (GTK3) completed successfully"
|
||||
|
||||
- name: Build Examples (GTK4)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
working-directory: v3
|
||||
run: |
|
||||
echo "Starting example compilation tests (GTK4)..."
|
||||
BUILD_TAGS=gtk4 task test:examples
|
||||
echo "Example compilation tests (GTK4) completed successfully"
|
||||
|
||||
- name: Run tests (mac)
|
||||
if: matrix.os == 'macos-latest'
|
||||
env:
|
||||
CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13
|
||||
working-directory: v3
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Run tests (windows)
|
||||
if: matrix.os == 'windows-latest'
|
||||
working-directory: v3
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Run tests (ubuntu) - GTK3 default
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
working-directory: v3
|
||||
run: >
|
||||
xvfb-run --auto-servernum
|
||||
sh -c '
|
||||
dbus-update-activation-environment --systemd --all &&
|
||||
go test -v ./...
|
||||
'
|
||||
|
||||
- name: Run tests (ubuntu) - GTK4
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
working-directory: v3
|
||||
# Skip service tests that hang in CI due to GTK4 display requirements
|
||||
run: >
|
||||
xvfb-run --auto-servernum
|
||||
sh -c '
|
||||
dbus-update-activation-environment --systemd --all &&
|
||||
go test -tags gtk4 -v -skip "TestService" ./...
|
||||
'
|
||||
|
||||
- name: Typecheck binding generator output
|
||||
working-directory: v3
|
||||
run: task generator:test:check
|
||||
|
||||
cleanup:
|
||||
name: Cleanup build artifacts
|
||||
if: always()
|
||||
needs: [test_js, test_go, test_templates]
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: geekyeggo/delete-artifact@v5
|
||||
with:
|
||||
name: |
|
||||
runtime-build-artifacts
|
||||
runtime-package
|
||||
failOnError: false
|
||||
- name: Run tests
|
||||
run: npm test
|
||||
working-directory: v2/internal/frontend/runtime
|
||||
|
||||
test_templates:
|
||||
name: Test Templates
|
||||
needs: [test_js, test_go]
|
||||
needs: test_go
|
||||
runs-on: ${{ matrix.os }}
|
||||
if: github.base_ref == 'v3-alpha'
|
||||
strategy:
|
||||
|
|
@ -235,24 +146,17 @@ jobs:
|
|||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Install linux dependencies (GTK3)
|
||||
- name: Install linux dependencies
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config
|
||||
version: 1.0
|
||||
|
||||
- name: Install linux dependencies (GTK4)
|
||||
if: matrix.os == 'ubuntu-latest'
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-4-dev libwebkitgtk-6.0-dev
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
cache: true
|
||||
cache-dependency-path: "v3/go.sum"
|
||||
|
||||
- name: Install Task
|
||||
|
|
@ -267,32 +171,14 @@ jobs:
|
|||
task install
|
||||
wails3 doctor
|
||||
|
||||
- name: Download runtime package
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
name: runtime-package
|
||||
path: wails-runtime-temp
|
||||
|
||||
- name: Generate template '${{ matrix.template }}' (GTK3 default)
|
||||
shell: bash
|
||||
- name: Generate template '${{ matrix.template }}'
|
||||
run: |
|
||||
# Get absolute path - use pwd -W on Windows for native paths, pwd elsewhere
|
||||
if [[ "$RUNNER_OS" == "Windows" ]]; then
|
||||
RUNTIME_TGZ="$(cd wails-runtime-temp && pwd -W)/$(ls wails-runtime-temp/*.tgz | xargs basename)"
|
||||
else
|
||||
RUNTIME_TGZ="$(cd wails-runtime-temp && pwd)/$(ls wails-runtime-temp/*.tgz | xargs basename)"
|
||||
fi
|
||||
mkdir -p ./test-${{ matrix.template }}
|
||||
cd ./test-${{ matrix.template }}
|
||||
wails3 init -n ${{ matrix.template }} -t ${{ matrix.template }}
|
||||
cd ${{ matrix.template }}/frontend
|
||||
# Replace @wailsio/runtime version with local tarball
|
||||
npm pkg set dependencies.@wailsio/runtime="file://$RUNTIME_TGZ"
|
||||
cd ..
|
||||
cd ${{ matrix.template }}
|
||||
wails3 build
|
||||
|
||||
# GTK4 template builds are covered by the Go example compilation tests above.
|
||||
|
||||
build_results:
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
|
|
|
|||
36
.github/workflows/build-and-test.yml
vendored
|
|
@ -12,8 +12,8 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, ubuntu-24.04, windows-latest, macos-latest, macos-11]
|
||||
go-version: ['1.21']
|
||||
os: [ubuntu-22.04, ubuntu-24.04, windows-latest, macos-latest]
|
||||
go-version: ['1.22']
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
|
|
@ -28,7 +28,7 @@ jobs:
|
|||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-24.04'
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config libegl1
|
||||
version: 1.0
|
||||
|
||||
- name: Setup Go
|
||||
|
|
@ -38,14 +38,14 @@ jobs:
|
|||
cache-dependency-path: ./v2/go.sum
|
||||
|
||||
- name: Run tests (mac)
|
||||
if: matrix.os == 'macos-latest' || matrix.os == 'macos-11'
|
||||
if: matrix.os == 'macos-latest'
|
||||
env:
|
||||
CGO_LDFLAGS: -framework UniformTypeIdentifiers -mmacosx-version-min=10.13
|
||||
working-directory: ./v2
|
||||
run: go test -v ./...
|
||||
|
||||
- name: Run tests (!mac)
|
||||
if: matrix.os != 'macos-latest' && matrix.os != 'macos-11' && matrix.os != 'ubuntu-24.04'
|
||||
if: matrix.os != 'macos-latest' && matrix.os != 'ubuntu-24.04'
|
||||
working-directory: ./v2
|
||||
run: go test -v ./...
|
||||
|
||||
|
|
@ -86,7 +86,7 @@ jobs:
|
|||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
os: [ubuntu-22.04, windows-latest, macos-latest, ubuntu-24.04, macos-11]
|
||||
os: [ubuntu-22.04, windows-latest, macos-latest, ubuntu-24.04]
|
||||
template:
|
||||
[
|
||||
svelte,
|
||||
|
|
@ -103,13 +103,13 @@ jobs:
|
|||
vanilla-ts,
|
||||
plain,
|
||||
]
|
||||
go-version: ['1.21']
|
||||
go-version: ['1.22']
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ${{ matrix.go-version }}
|
||||
cache-dependency-path: ./v2/go.sum
|
||||
|
|
@ -120,13 +120,25 @@ jobs:
|
|||
go install
|
||||
wails -help
|
||||
|
||||
- name: Install linux dependencies ( 22.04 )
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-22.04'
|
||||
run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
|
||||
version: 1.0
|
||||
|
||||
- name: Install linux dependencies ( 24.04 )
|
||||
# - name: Install linux dependencies ( 22.04 )
|
||||
# if: matrix.os == 'ubuntu-22.04'
|
||||
# run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.0-dev build-essential pkg-config
|
||||
|
||||
- uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
if: matrix.os == 'ubuntu-24.04'
|
||||
run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config libegl1
|
||||
version: 1.0
|
||||
|
||||
# - name: Install linux dependencies ( 24.04 )
|
||||
# if: matrix.os == 'ubuntu-24.04'
|
||||
# run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config
|
||||
|
||||
- name: Generate & Build template '${{ matrix.template }}'
|
||||
if: matrix.os != 'ubuntu-24.04'
|
||||
|
|
|
|||
332
.github/workflows/build-cross-image.yml
vendored
|
|
@ -94,18 +94,10 @@ jobs:
|
|||
build-args: |
|
||||
ZIG_VERSION=${{ steps.vars.outputs.zig_version }}
|
||||
MACOS_SDK_VERSION=${{ steps.vars.outputs.sdk_version }}
|
||||
cache-from: |
|
||||
type=gha
|
||||
type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache
|
||||
cache-to: |
|
||||
type=gha,mode=max
|
||||
type=registry,ref=${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:buildcache,mode=max
|
||||
cache-from: type=gha
|
||||
cache-to: type=gha,mode=max
|
||||
|
||||
# Test cross-compilation using wails3 task system (3 parallel jobs)
|
||||
# Runs on Linux/amd64 runner - tests actual cross-compilation only:
|
||||
# - darwin: cross-platform (arm64)
|
||||
# - windows: cross-platform (arm64)
|
||||
# - linux: cross-architecture (arm64 from amd64 runner)
|
||||
# Test cross-compilation for all platforms
|
||||
test-cross-compile:
|
||||
needs: build
|
||||
if: ${{ inputs.skip_tests != 'true' }}
|
||||
|
|
@ -114,24 +106,33 @@ jobs:
|
|||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
# Darwin arm64 (Intel Macs are EOL, skip amd64)
|
||||
# Darwin targets (Zig + macOS SDK) - no platform emulation needed
|
||||
- os: darwin
|
||||
arch: arm64
|
||||
expected: "Mach-O 64-bit.*arm64"
|
||||
# Windows - both archs
|
||||
- os: windows
|
||||
platform: ""
|
||||
expected_file: "Mach-O 64-bit.*arm64"
|
||||
- os: darwin
|
||||
arch: amd64
|
||||
expected: "PE32.*x86-64"
|
||||
- os: windows
|
||||
arch: arm64
|
||||
expected: "PE32.*Aarch64"
|
||||
# Linux - both archs via Docker
|
||||
platform: ""
|
||||
expected_file: "Mach-O 64-bit.*x86_64"
|
||||
# Linux targets (GCC) - need platform to match architecture
|
||||
- os: linux
|
||||
arch: amd64
|
||||
expected: "ELF 64-bit LSB.*x86-64"
|
||||
platform: "linux/amd64"
|
||||
expected_file: "ELF 64-bit LSB.*x86-64"
|
||||
- os: linux
|
||||
arch: arm64
|
||||
expected: "ELF 64-bit LSB.*ARM aarch64"
|
||||
platform: "linux/arm64"
|
||||
expected_file: "ELF 64-bit LSB.*ARM aarch64"
|
||||
# Windows targets (Zig + mingw) - no platform emulation needed
|
||||
- os: windows
|
||||
arch: amd64
|
||||
platform: ""
|
||||
expected_file: "PE32\\+ executable.*x86-64"
|
||||
- os: windows
|
||||
arch: arm64
|
||||
platform: ""
|
||||
expected_file: "PE32\\+ executable.*Aarch64"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
|
|
@ -139,29 +140,8 @@ jobs:
|
|||
with:
|
||||
ref: ${{ inputs.branch || github.ref }}
|
||||
|
||||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.24'
|
||||
cache: false
|
||||
|
||||
- name: Set up Node.js
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: '20'
|
||||
|
||||
- name: Install Linux dev dependencies
|
||||
run: |
|
||||
sudo apt-get update
|
||||
sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev
|
||||
|
||||
- name: Install wails3 CLI
|
||||
run: |
|
||||
cd v3
|
||||
go install ./cmd/wails3
|
||||
|
||||
- name: Set up QEMU
|
||||
if: matrix.os == 'linux'
|
||||
if: matrix.platform != ''
|
||||
uses: docker/setup-qemu-action@v3
|
||||
|
||||
- name: Log in to Container Registry
|
||||
|
|
@ -171,74 +151,95 @@ jobs:
|
|||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Pull and tag Docker image
|
||||
- name: Create test CGO project
|
||||
run: |
|
||||
# Pull both platform variants and tag them for the task system
|
||||
# The task uses --platform flag which requires matching arch variant
|
||||
IMAGE="${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag || 'latest' }}"
|
||||
mkdir -p test-project
|
||||
cd test-project
|
||||
|
||||
# For Linux arm64 test, we need the arm64 variant
|
||||
if [ "${{ matrix.os }}" = "linux" ] && [ "${{ matrix.arch }}" = "arm64" ]; then
|
||||
docker pull --platform linux/arm64 "$IMAGE"
|
||||
docker tag "$IMAGE" wails-cross
|
||||
else
|
||||
docker pull "$IMAGE"
|
||||
docker tag "$IMAGE" wails-cross
|
||||
# Create a minimal CGO test program
|
||||
cat > main.go << 'EOF'
|
||||
package main
|
||||
|
||||
/*
|
||||
#include <stdlib.h>
|
||||
|
||||
int add(int a, int b) {
|
||||
return a + b;
|
||||
}
|
||||
*/
|
||||
import "C"
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
result := C.add(1, 2)
|
||||
fmt.Printf("CGO test: 1 + 2 = %d\n", result)
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > go.mod << 'EOF'
|
||||
module test-cgo
|
||||
|
||||
go 1.21
|
||||
EOF
|
||||
|
||||
- name: Build ${{ matrix.os }}/${{ matrix.arch }} (CGO)
|
||||
run: |
|
||||
cd test-project
|
||||
PLATFORM_FLAG=""
|
||||
if [ -n "${{ matrix.platform }}" ]; then
|
||||
PLATFORM_FLAG="--platform ${{ matrix.platform }}"
|
||||
fi
|
||||
|
||||
- name: Generate wails3 test project
|
||||
run: |
|
||||
cd /tmp
|
||||
wails3 init -n test-wails-app -t vanilla
|
||||
cd test-wails-app
|
||||
docker run --rm $PLATFORM_FLAG \
|
||||
-v "$(pwd):/app" \
|
||||
-e APP_NAME="test-cgo" \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag || 'latest' }} \
|
||||
${{ matrix.os }} ${{ matrix.arch }}
|
||||
|
||||
# Update replace directive to use absolute path (wails3 init adds relative path)
|
||||
sed -i 's|replace github.com/wailsapp/wails/v3 => .*|replace github.com/wailsapp/wails/v3 => ${{ github.workspace }}/v3|' go.mod
|
||||
|
||||
- name: Cross-compile ${{ matrix.os }}/${{ matrix.arch }} via task
|
||||
- name: Verify binary format
|
||||
run: |
|
||||
cd /tmp/test-wails-app
|
||||
# For Linux, always use docker build to test the Docker image
|
||||
if [ "${{ matrix.os }}" = "linux" ]; then
|
||||
wails3 task linux:build:docker ARCH=${{ matrix.arch }}
|
||||
else
|
||||
wails3 task ${{ matrix.os }}:build ARCH=${{ matrix.arch }}
|
||||
fi
|
||||
|
||||
- name: Verify binary
|
||||
run: |
|
||||
cd /tmp/test-wails-app/bin
|
||||
cd test-project/bin
|
||||
ls -la
|
||||
|
||||
# Find the built binary
|
||||
if [ "${{ matrix.os }}" = "windows" ]; then
|
||||
BINARY="test-wails-app.exe"
|
||||
BINARY=$(ls test-cgo-${{ matrix.os }}-${{ matrix.arch }}.exe 2>/dev/null || ls *.exe | head -1)
|
||||
else
|
||||
BINARY="test-wails-app"
|
||||
BINARY=$(ls test-cgo-${{ matrix.os }}-${{ matrix.arch }} 2>/dev/null || ls test-cgo* | grep -v '.exe' | head -1)
|
||||
fi
|
||||
|
||||
echo "Checking: $BINARY"
|
||||
echo "Binary: $BINARY"
|
||||
FILE_OUTPUT=$(file "$BINARY")
|
||||
echo " $FILE_OUTPUT"
|
||||
echo "File output: $FILE_OUTPUT"
|
||||
|
||||
if echo "$FILE_OUTPUT" | grep -qE "${{ matrix.expected }}"; then
|
||||
echo " ✅ Cross-compilation verified: ${{ matrix.os }}/${{ matrix.arch }}"
|
||||
# Verify the binary format matches expected
|
||||
if echo "$FILE_OUTPUT" | grep -qE "${{ matrix.expected_file }}"; then
|
||||
echo "✅ Binary format verified: ${{ matrix.os }}/${{ matrix.arch }}"
|
||||
else
|
||||
echo " ❌ Format mismatch! Expected: ${{ matrix.expected }}"
|
||||
echo "❌ Binary format mismatch!"
|
||||
echo "Expected pattern: ${{ matrix.expected_file }}"
|
||||
echo "Got: $FILE_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check library dependencies (Linux only)
|
||||
if: matrix.os == 'linux'
|
||||
run: |
|
||||
cd /tmp/test-wails-app/bin
|
||||
cd test-project/bin
|
||||
BINARY=$(ls test-cgo-${{ matrix.os }}-${{ matrix.arch }} 2>/dev/null || ls test-cgo* | grep -v '.exe' | head -1)
|
||||
|
||||
echo "## Library Dependencies"
|
||||
echo "## Library Dependencies for $BINARY"
|
||||
echo ""
|
||||
|
||||
# Use readelf to show dynamic dependencies
|
||||
echo "### NEEDED libraries:"
|
||||
readelf -d test-wails-app | grep NEEDED || echo "No dynamic dependencies"
|
||||
echo ""
|
||||
readelf -d "$BINARY" | grep NEEDED || echo "No dynamic dependencies (statically linked)"
|
||||
|
||||
# Verify expected libraries are linked
|
||||
echo ""
|
||||
echo "### Verifying required libraries..."
|
||||
NEEDED=$(readelf -d "$BINARY" | grep NEEDED)
|
||||
|
||||
NEEDED=$(readelf -d test-wails-app | grep NEEDED)
|
||||
MISSING=""
|
||||
for lib in libwebkit2gtk-4.1.so libgtk-3.so libglib-2.0.so libc.so; do
|
||||
if echo "$NEEDED" | grep -q "$lib"; then
|
||||
|
|
@ -250,13 +251,139 @@ jobs:
|
|||
done
|
||||
|
||||
if [ -n "$MISSING" ]; then
|
||||
echo ""
|
||||
echo "ERROR: Missing required libraries:$MISSING"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Test non-CGO builds (pure Go cross-compilation)
|
||||
test-non-cgo:
|
||||
needs: build
|
||||
if: ${{ inputs.skip_tests != 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- os: darwin
|
||||
arch: arm64
|
||||
expected_file: "Mach-O 64-bit.*arm64"
|
||||
- os: darwin
|
||||
arch: amd64
|
||||
expected_file: "Mach-O 64-bit.*x86_64"
|
||||
- os: linux
|
||||
arch: amd64
|
||||
expected_file: "ELF 64-bit LSB"
|
||||
- os: linux
|
||||
arch: arm64
|
||||
expected_file: "ELF 64-bit LSB.*ARM aarch64"
|
||||
- os: windows
|
||||
arch: amd64
|
||||
expected_file: "PE32\\+ executable.*x86-64"
|
||||
- os: windows
|
||||
arch: arm64
|
||||
expected_file: "PE32\\+ executable.*Aarch64"
|
||||
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ inputs.branch || github.ref }}
|
||||
|
||||
- name: Log in to Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Create test non-CGO project
|
||||
run: |
|
||||
mkdir -p test-project
|
||||
cd test-project
|
||||
|
||||
# Create a pure Go test program (no CGO)
|
||||
cat > main.go << 'EOF'
|
||||
package main
|
||||
|
||||
import "fmt"
|
||||
|
||||
func main() {
|
||||
fmt.Println("Pure Go cross-compilation test")
|
||||
}
|
||||
EOF
|
||||
|
||||
cat > go.mod << 'EOF'
|
||||
module test-pure-go
|
||||
|
||||
go 1.21
|
||||
EOF
|
||||
|
||||
- name: Build ${{ matrix.os }}/${{ matrix.arch }} (non-CGO)
|
||||
run: |
|
||||
cd test-project
|
||||
|
||||
# For non-CGO, we can use any platform since Go handles cross-compilation
|
||||
# We set CGO_ENABLED=0 to ensure pure Go build
|
||||
docker run --rm \
|
||||
-v "$(pwd):/app" \
|
||||
-e APP_NAME="test-pure-go" \
|
||||
-e CGO_ENABLED=0 \
|
||||
--entrypoint /bin/sh \
|
||||
${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}:${{ needs.build.outputs.image_tag || 'latest' }} \
|
||||
-c "GOOS=${{ matrix.os }} GOARCH=${{ matrix.arch }} go build -o bin/test-pure-go-${{ matrix.os }}-${{ matrix.arch }}${{ matrix.os == 'windows' && '.exe' || '' }} ."
|
||||
|
||||
- name: Verify binary format
|
||||
run: |
|
||||
cd test-project/bin
|
||||
ls -la
|
||||
|
||||
# Find the built binary
|
||||
if [ "${{ matrix.os }}" = "windows" ]; then
|
||||
BINARY="test-pure-go-${{ matrix.os }}-${{ matrix.arch }}.exe"
|
||||
else
|
||||
BINARY="test-pure-go-${{ matrix.os }}-${{ matrix.arch }}"
|
||||
fi
|
||||
|
||||
echo "Binary: $BINARY"
|
||||
FILE_OUTPUT=$(file "$BINARY")
|
||||
echo "File output: $FILE_OUTPUT"
|
||||
|
||||
# Verify the binary format matches expected
|
||||
if echo "$FILE_OUTPUT" | grep -qE "${{ matrix.expected_file }}"; then
|
||||
echo "✅ Binary format verified: ${{ matrix.os }}/${{ matrix.arch }} (non-CGO)"
|
||||
else
|
||||
echo "❌ Binary format mismatch!"
|
||||
echo "Expected pattern: ${{ matrix.expected_file }}"
|
||||
echo "Got: $FILE_OUTPUT"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
- name: Check library dependencies (Linux only)
|
||||
if: matrix.os == 'linux'
|
||||
run: |
|
||||
cd test-project/bin
|
||||
BINARY="test-pure-go-${{ matrix.os }}-${{ matrix.arch }}"
|
||||
|
||||
echo "## Library Dependencies for $BINARY (non-CGO)"
|
||||
echo ""
|
||||
|
||||
# Non-CGO builds should have minimal dependencies (just libc or statically linked)
|
||||
echo "### NEEDED libraries:"
|
||||
readelf -d "$BINARY" | grep NEEDED || echo "No dynamic dependencies (statically linked)"
|
||||
|
||||
# Verify NO GTK/WebKit libraries (since CGO is disabled)
|
||||
NEEDED=$(readelf -d "$BINARY" | grep NEEDED || true)
|
||||
if echo "$NEEDED" | grep -q "libwebkit\|libgtk"; then
|
||||
echo "❌ ERROR: Non-CGO binary should not link to GTK/WebKit!"
|
||||
exit 1
|
||||
else
|
||||
echo "✅ Confirmed: No GTK/WebKit dependencies (expected for non-CGO)"
|
||||
fi
|
||||
|
||||
# Summary job
|
||||
test-summary:
|
||||
needs: [build, test-cross-compile]
|
||||
needs: [build, test-cross-compile, test-non-cgo]
|
||||
if: always() && inputs.skip_tests != 'true'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
|
|
@ -266,23 +393,30 @@ jobs:
|
|||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
if [ "${{ needs.test-cross-compile.result }}" = "success" ]; then
|
||||
echo "✅ **All Tests Passed**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "✅ **CGO Tests**: All passed" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Some Tests Failed**" >> $GITHUB_STEP_SUMMARY
|
||||
echo "❌ **CGO Tests**: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
if [ "${{ needs.test-non-cgo.result }}" = "success" ]; then
|
||||
echo "✅ **Non-CGO Tests**: All passed" >> $GITHUB_STEP_SUMMARY
|
||||
else
|
||||
echo "❌ **Non-CGO Tests**: Failed" >> $GITHUB_STEP_SUMMARY
|
||||
fi
|
||||
|
||||
echo "" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Cross-Compilation Tests (from Linux/amd64 runner)" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Target | Status |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|--------|--------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Darwin/arm64 | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows/amd64 | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows/arm64 | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux/amd64 | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux/arm64 | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "### Tested Platforms" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Platform | Architecture | CGO | Non-CGO |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "|----------|-------------|-----|---------|" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Darwin | arm64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Darwin | amd64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux | arm64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Linux | amd64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows | arm64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
echo "| Windows | amd64 | ✅ | ✅ |" >> $GITHUB_STEP_SUMMARY
|
||||
|
||||
# Fail if any test failed
|
||||
if [ "${{ needs.test-cross-compile.result }}" != "success" ]; then
|
||||
if [ "${{ needs.test-cross-compile.result }}" != "success" ] || [ "${{ needs.test-non-cgo.result }}" != "success" ]; then
|
||||
echo ""
|
||||
echo "❌ Some tests failed. Check the individual job logs for details."
|
||||
exit 1
|
||||
|
|
|
|||
216
.github/workflows/changelog-v3.yml
vendored
Normal file
|
|
@ -0,0 +1,216 @@
|
|||
name: Changelog Validation (v3)
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ v3-alpha ]
|
||||
paths:
|
||||
- 'docs/src/content/docs/changelog.mdx'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to validate'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
validate:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
actions: write
|
||||
|
||||
steps:
|
||||
- name: Checkout PR code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.inputs.pr_number) }}
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN || github.token }}
|
||||
|
||||
- name: Get REAL validation script from v3-alpha
|
||||
run: |
|
||||
echo "Fetching the REAL validation script from v3-alpha branch..."
|
||||
git fetch origin v3-alpha
|
||||
git checkout origin/v3-alpha -- v3/scripts/validate-changelog.go
|
||||
|
||||
echo "Validation script fetched successfully:"
|
||||
ls -la v3/scripts/
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23'
|
||||
|
||||
- name: Get PR information
|
||||
id: pr_info
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
||||
echo "base_ref=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "pr_number=${{ github.event.inputs.pr_number }}" >> $GITHUB_OUTPUT
|
||||
echo "base_ref=v3-alpha" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check changelog modifications
|
||||
id: changelog_check
|
||||
run: |
|
||||
echo "Checking PR #${{ steps.pr_info.outputs.pr_number }} for changelog changes"
|
||||
git fetch origin ${{ steps.pr_info.outputs.base_ref }}
|
||||
|
||||
if git diff --name-only origin/${{ steps.pr_info.outputs.base_ref }}..HEAD | grep -q "docs/src/content/docs/changelog.mdx"; then
|
||||
echo "changelog_modified=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Changelog was modified in this PR"
|
||||
else
|
||||
echo "changelog_modified=false" >> $GITHUB_OUTPUT
|
||||
echo "ℹ️ Changelog was not modified - skipping validation"
|
||||
fi
|
||||
|
||||
- name: Get changelog diff
|
||||
id: get_diff
|
||||
if: steps.changelog_check.outputs.changelog_modified == 'true'
|
||||
run: |
|
||||
echo "Getting diff for changelog changes..."
|
||||
git diff origin/${{ steps.pr_info.outputs.base_ref }}..HEAD docs/src/content/docs/changelog.mdx | grep "^+" | grep -v "^+++" | sed 's/^+//' > /tmp/pr_added_lines.txt
|
||||
|
||||
echo "Lines added in this PR:"
|
||||
cat /tmp/pr_added_lines.txt
|
||||
echo "Total lines added: $(wc -l < /tmp/pr_added_lines.txt)"
|
||||
|
||||
- name: Validate changelog
|
||||
id: validate
|
||||
if: steps.changelog_check.outputs.changelog_modified == 'true'
|
||||
run: |
|
||||
echo "Running changelog validation..."
|
||||
cd v3/scripts
|
||||
OUTPUT=$(go run validate-changelog.go ../../docs/src/content/docs/changelog.mdx /tmp/pr_added_lines.txt 2>&1)
|
||||
echo "$OUTPUT"
|
||||
|
||||
RESULT=$(echo "$OUTPUT" | grep "VALIDATION_RESULT=" | cut -d'=' -f2)
|
||||
echo "result=$RESULT" >> $GITHUB_OUTPUT
|
||||
|
||||
- name: Commit fixes
|
||||
id: commit_fixes
|
||||
if: steps.validate.outputs.result == 'fixed'
|
||||
run: |
|
||||
echo "Committing automatic fixes..."
|
||||
git config --local user.email "action@github.com"
|
||||
git config --local user.name "GitHub Action"
|
||||
|
||||
# Check only the changelog file for changes
|
||||
if git diff --quiet docs/src/content/docs/changelog.mdx; then
|
||||
echo "No changes to commit"
|
||||
echo "committed=false" >> $GITHUB_OUTPUT
|
||||
else
|
||||
# Ensure validation script doesn't get committed
|
||||
echo "v3/scripts/validate-changelog.go" >> .git/info/exclude
|
||||
# Get the correct branch name to push to
|
||||
REPO_OWNER="wailsapp" # Always wailsapp for this repo
|
||||
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
BRANCH_NAME="${{ github.event.pull_request.head.ref }}"
|
||||
else
|
||||
# For manual workflow dispatch, get PR info
|
||||
PR_INFO=$(gh pr view ${{ steps.pr_info.outputs.pr_number }} --json headRefName,headRepository)
|
||||
BRANCH_NAME=$(echo "$PR_INFO" | jq -r '.headRefName')
|
||||
HEAD_REPO=$(echo "$PR_INFO" | jq -r '.headRepository.name')
|
||||
|
||||
echo "🔍 PR source branch: $BRANCH_NAME"
|
||||
echo "🔍 Head repository: $HEAD_REPO"
|
||||
|
||||
# Don't push if this is from a fork or if branch is v3-alpha (main branch)
|
||||
if [ "$HEAD_REPO" != "wails" ] || [ "$BRANCH_NAME" = "v3-alpha" ]; then
|
||||
echo "⚠️ Cannot push - either fork or direct v3-alpha branch. Manual fix required."
|
||||
echo "committed=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
fi
|
||||
|
||||
echo "Pushing to branch: $BRANCH_NAME in repo: $REPO_OWNER"
|
||||
|
||||
# Only commit the changelog changes, not the validation script
|
||||
git add docs/src/content/docs/changelog.mdx
|
||||
git commit -m "🤖 Fix changelog: move entries to Unreleased section"
|
||||
|
||||
# Only push if running on the main wailsapp repository
|
||||
if [ "${{ github.repository }}" = "wailsapp/wails" ]; then
|
||||
# Pull latest changes and rebase our commit
|
||||
git fetch origin $BRANCH_NAME
|
||||
git rebase origin/$BRANCH_NAME
|
||||
git push origin HEAD:$BRANCH_NAME
|
||||
else
|
||||
echo "⚠️ Running on fork (${{ github.repository }}). Skipping push - manual fix required."
|
||||
echo "committed=false" >> $GITHUB_OUTPUT
|
||||
exit 0
|
||||
fi
|
||||
|
||||
echo "committed=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ Changes committed and pushed"
|
||||
fi
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Get PR author for tagging
|
||||
id: pr_author
|
||||
if: steps.validate.outputs.result && github.event.inputs.pr_number
|
||||
run: |
|
||||
PR_AUTHOR=$(gh pr view ${{ steps.pr_info.outputs.pr_number }} --json author --jq '.author.login')
|
||||
echo "author=$PR_AUTHOR" >> $GITHUB_OUTPUT
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Comment on PR
|
||||
if: steps.validate.outputs.result && github.event.inputs.pr_number
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const result = '${{ steps.validate.outputs.result }}';
|
||||
const committed = '${{ steps.commit_fixes.outputs.committed }}';
|
||||
const author = '${{ steps.pr_author.outputs.author }}';
|
||||
|
||||
let message;
|
||||
if (result === 'success') {
|
||||
message = '## ✅ Changelog Validation Passed\n\nNo misplaced changelog entries detected.';
|
||||
} else if (result === 'fixed' && committed === 'true') {
|
||||
message = '## 🔧 Changelog Updated\n\nMisplaced entries were automatically moved to the `[Unreleased]` section. The changes have been committed to this PR.';
|
||||
} else if (result === 'fixed' || result === 'cannot_fix' || result === 'error') {
|
||||
// Read the fixed changelog content
|
||||
const fs = require('fs');
|
||||
let fixedContent = '';
|
||||
try {
|
||||
fixedContent = fs.readFileSync('docs/src/content/docs/changelog.mdx', 'utf8');
|
||||
} catch (error) {
|
||||
fixedContent = 'Error reading fixed changelog content';
|
||||
}
|
||||
|
||||
message = '## ⚠️ Changelog Validation Issue\\n\\n' +
|
||||
'@' + author + ' Your PR contains changelog entries that were added to already-released versions. These need to be moved to the `[Unreleased]` section.\\n\\n' +
|
||||
(committed === 'true' ?
|
||||
'✅ **Auto-fix applied**: The changes have been automatically committed to this PR.' :
|
||||
'❌ **Manual fix required**: Please apply the changes shown below manually.') + '\\n\\n' +
|
||||
'<details>\\n' +
|
||||
'<summary>📝 Click to see the corrected changelog content</summary>\\n\\n' +
|
||||
'```mdx\\n' +
|
||||
fixedContent +
|
||||
'\\n```\\n\\n' +
|
||||
'</details>\\n\\n' +
|
||||
'**What happened?** \\n' +
|
||||
'The validation script detected that you added changelog entries to a version section that has already been released (like `v3.0.0-alpha.10`). All new entries should go in the `[Unreleased]` section under the appropriate category (`### Added`, `### Fixed`, etc.).\\n\\n' +
|
||||
(committed !== 'true' ? '**Action needed:** Please copy the corrected content from above and replace your changelog file.' : '');
|
||||
}
|
||||
|
||||
if (message) {
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: ${{ steps.pr_info.outputs.pr_number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: message
|
||||
});
|
||||
}
|
||||
|
||||
- name: Fail if validation failed
|
||||
if: steps.validate.outputs.result == 'cannot_fix' || steps.validate.outputs.result == 'error'
|
||||
run: |
|
||||
echo "❌ Changelog validation failed"
|
||||
exit 1
|
||||
74
.github/workflows/changelog-validation-v3.yml
vendored
|
|
@ -1,74 +0,0 @@
|
|||
name: Changelog Validation (v3)
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
branches: [ v3-alpha ]
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to validate (for manual testing)'
|
||||
required: true
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
validate-changelog:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'pull_request' || github.event.inputs.pr_number
|
||||
|
||||
permissions:
|
||||
contents: write
|
||||
pull-requests: write
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.event.pull_request.head.sha || format('refs/pull/{0}/head', github.event.inputs.pr_number) }}
|
||||
fetch-depth: 0
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v4
|
||||
with:
|
||||
go-version: '1.23'
|
||||
|
||||
- name: Get PR information
|
||||
id: pr_info
|
||||
run: |
|
||||
if [ "${{ github.event_name }}" = "pull_request" ]; then
|
||||
echo "pr_number=${{ github.event.pull_request.number }}" >> $GITHUB_OUTPUT
|
||||
echo "base_ref=${{ github.event.pull_request.base.ref }}" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "pr_number=${{ github.event.inputs.pr_number }}" >> $GITHUB_OUTPUT
|
||||
echo "base_ref=v3-alpha" >> $GITHUB_OUTPUT
|
||||
fi
|
||||
|
||||
- name: Check if changelog was modified
|
||||
id: changelog_check
|
||||
run: |
|
||||
git fetch origin ${{ steps.pr_info.outputs.base_ref }}
|
||||
if git diff --name-only origin/${{ steps.pr_info.outputs.base_ref }}..HEAD | grep -q "v3/UNRELEASED_CHANGELOG.md"; then
|
||||
echo "changelog_modified=true" >> $GITHUB_OUTPUT
|
||||
echo "✅ UNRELEASED_CHANGELOG.md was modified in this PR"
|
||||
else
|
||||
echo "changelog_modified=false" >> $GITHUB_OUTPUT
|
||||
echo "⚠️ UNRELEASED_CHANGELOG.md was not modified"
|
||||
fi
|
||||
|
||||
- name: Comment on PR about missing changelog
|
||||
if: steps.changelog_check.outputs.changelog_modified == 'false' && github.event_name == 'pull_request'
|
||||
uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
const author = context.payload.pull_request.user.login;
|
||||
const message = '## ⚠️ Missing Changelog Update\n\n' +
|
||||
`Hi @${author}, please update \`v3/UNRELEASED_CHANGELOG.md\` with a description of your changes.\n\n` +
|
||||
'This helps us keep track of changes for the next release.';
|
||||
|
||||
await github.rest.issues.createComment({
|
||||
issue_number: ${{ steps.pr_info.outputs.pr_number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: message
|
||||
});
|
||||
|
||||
44
.github/workflows/claude-code-review.yml
vendored
Normal file
|
|
@ -0,0 +1,44 @@
|
|||
name: Claude Code Review
|
||||
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, ready_for_review, reopened]
|
||||
# Optional: Only run on specific file changes
|
||||
# paths:
|
||||
# - "src/**/*.ts"
|
||||
# - "src/**/*.tsx"
|
||||
# - "src/**/*.js"
|
||||
# - "src/**/*.jsx"
|
||||
|
||||
jobs:
|
||||
claude-review:
|
||||
# Optional: Filter by PR author
|
||||
# if: |
|
||||
# github.event.pull_request.user.login == 'external-contributor' ||
|
||||
# github.event.pull_request.user.login == 'new-developer' ||
|
||||
# github.event.pull_request.author_association == 'FIRST_TIME_CONTRIBUTOR'
|
||||
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code Review
|
||||
id: claude-review
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
plugin_marketplaces: 'https://github.com/anthropics/claude-code.git'
|
||||
plugins: 'code-review@claude-code-plugins'
|
||||
prompt: '/code-review:code-review ${{ github.repository }}/pull/${{ github.event.pull_request.number }}'
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
|
||||
50
.github/workflows/claude.yml
vendored
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
name: Claude Code
|
||||
|
||||
on:
|
||||
issue_comment:
|
||||
types: [created]
|
||||
pull_request_review_comment:
|
||||
types: [created]
|
||||
issues:
|
||||
types: [opened, assigned]
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
|
||||
jobs:
|
||||
claude:
|
||||
if: |
|
||||
(github.event_name == 'issue_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review_comment' && contains(github.event.comment.body, '@claude')) ||
|
||||
(github.event_name == 'pull_request_review' && contains(github.event.review.body, '@claude')) ||
|
||||
(github.event_name == 'issues' && (contains(github.event.issue.body, '@claude') || contains(github.event.issue.title, '@claude')))
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: read
|
||||
pull-requests: read
|
||||
issues: read
|
||||
id-token: write
|
||||
actions: read # Required for Claude to read CI results on PRs
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 1
|
||||
|
||||
- name: Run Claude Code
|
||||
id: claude
|
||||
uses: anthropics/claude-code-action@v1
|
||||
with:
|
||||
claude_code_oauth_token: ${{ secrets.CLAUDE_CODE_OAUTH_TOKEN }}
|
||||
|
||||
# This is an optional setting that allows Claude to read CI results on PRs
|
||||
additional_permissions: |
|
||||
actions: read
|
||||
|
||||
# Optional: Give a custom prompt to Claude. If this is not specified, Claude will perform the instructions specified in the comment that tagged it.
|
||||
# prompt: 'Update the pull request description to include a summary of changes.'
|
||||
|
||||
# Optional: Add claude_args to customize behavior and configuration
|
||||
# See https://github.com/anthropics/claude-code-action/blob/main/docs/usage.md
|
||||
# or https://code.claude.com/docs/en/cli-reference for available options
|
||||
# claude_args: '--allowed-tools Bash(gh pr:*)'
|
||||
|
||||
135
.github/workflows/cross-compile-test-v3.yml
vendored
|
|
@ -1,135 +0,0 @@
|
|||
name: Cross-Compile Test v3
|
||||
|
||||
on:
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
branches:
|
||||
- v3-alpha
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
pr_number:
|
||||
description: 'PR number to test (optional, uses current branch if not specified)'
|
||||
required: false
|
||||
type: string
|
||||
|
||||
jobs:
|
||||
check_approval:
|
||||
name: Check PR Approval
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event_name == 'workflow_dispatch' || github.event.review.state == 'approved'
|
||||
outputs:
|
||||
approved: ${{ steps.check.outputs.approved }}
|
||||
steps:
|
||||
- name: Check if PR is approved or manual dispatch
|
||||
id: check
|
||||
run: |
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
echo "Manual dispatch, proceeding with cross-compile tests"
|
||||
else
|
||||
echo "PR approved, proceeding with cross-compile tests"
|
||||
fi
|
||||
echo "approved=true" >> $GITHUB_OUTPUT
|
||||
|
||||
cross_compile:
|
||||
name: Cross-Compile (${{ matrix.target_os }}/${{ matrix.target_arch }})
|
||||
needs: check_approval
|
||||
runs-on: ${{ matrix.runner }}
|
||||
if: needs.check_approval.outputs.approved == 'true'
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
include:
|
||||
- target_os: darwin
|
||||
target_arch: arm64
|
||||
runner: ubuntu-latest
|
||||
- target_os: darwin
|
||||
target_arch: amd64
|
||||
runner: ubuntu-latest
|
||||
- target_os: linux
|
||||
target_arch: arm64
|
||||
runner: ubuntu-24.04-arm # Native ARM64 runner - much faster than QEMU
|
||||
- target_os: linux
|
||||
target_arch: amd64
|
||||
runner: ubuntu-latest
|
||||
- target_os: windows
|
||||
target_arch: arm64
|
||||
runner: ubuntu-latest
|
||||
- target_os: windows
|
||||
target_arch: amd64
|
||||
runner: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Checkout PR (if specified)
|
||||
if: github.event_name == 'workflow_dispatch' && inputs.pr_number != ''
|
||||
run: gh pr checkout ${{ inputs.pr_number }}
|
||||
env:
|
||||
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.25'
|
||||
cache: true
|
||||
cache-dependency-path: "v3/go.sum"
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Install Linux dependencies
|
||||
uses: awalsh128/cache-apt-pkgs-action@latest
|
||||
with:
|
||||
packages: libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config
|
||||
version: 1.0
|
||||
|
||||
- name: Install Wails3 CLI
|
||||
working-directory: v3
|
||||
run: |
|
||||
go install ./cmd/wails3
|
||||
wails3 version
|
||||
|
||||
- name: Create test project
|
||||
run: |
|
||||
mkdir -p test-cross-compile
|
||||
cd test-cross-compile
|
||||
wails3 init -n crosstest -t vanilla
|
||||
|
||||
- name: Setup Docker cross-compile image
|
||||
working-directory: test-cross-compile/crosstest
|
||||
run: task common:setup:docker
|
||||
|
||||
- name: Fix replace directive for Docker build
|
||||
working-directory: test-cross-compile/crosstest
|
||||
run: |
|
||||
# Change the replace directive to use absolute path that matches Docker mount
|
||||
go mod edit -dropreplace github.com/wailsapp/wails/v3
|
||||
go mod edit -replace github.com/wailsapp/wails/v3=${{ github.workspace }}/v3
|
||||
|
||||
- name: Cross-compile for ${{ matrix.target_os }}/${{ matrix.target_arch }}
|
||||
working-directory: test-cross-compile/crosstest
|
||||
run: |
|
||||
echo "Cross-compiling for ${{ matrix.target_os }}/${{ matrix.target_arch }}..."
|
||||
task ${{ matrix.target_os }}:build ARCH=${{ matrix.target_arch }}
|
||||
echo "Cross-compilation successful!"
|
||||
ls -la bin/
|
||||
|
||||
cross_compile_results:
|
||||
if: ${{ always() }}
|
||||
runs-on: ubuntu-latest
|
||||
name: Cross-Compile Results
|
||||
needs: [cross_compile]
|
||||
steps:
|
||||
- run: |
|
||||
result="${{ needs.cross_compile.result }}"
|
||||
echo "Cross-compile result: $result"
|
||||
if [[ $result == "success" || $result == "skipped" ]]; then
|
||||
echo "Cross-compile tests passed (or were skipped)!"
|
||||
exit 0
|
||||
else
|
||||
echo "One or more cross-compile tests failed"
|
||||
exit 1
|
||||
fi
|
||||
2
.github/workflows/generate-sponsor-image.yml
vendored
|
|
@ -25,7 +25,7 @@ jobs:
|
|||
SPONSORKIT_GITHUB_LOGIN: wailsapp
|
||||
|
||||
- name: Create Pull Request
|
||||
uses: peter-evans/create-pull-request@v4
|
||||
uses: peter-evans/create-pull-request@v6
|
||||
with:
|
||||
commit-message: "chore: update sponsors.svg"
|
||||
add-paths: "website/static/img/sponsors.svg"
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ name: Issue Triage Automation
|
|||
|
||||
on:
|
||||
issues:
|
||||
types: [opened, reopened, labeled, unlabeled]
|
||||
types: [opened]
|
||||
|
||||
jobs:
|
||||
triage:
|
||||
|
|
|
|||
43
.github/workflows/pr-master.yml
vendored
|
|
@ -1,17 +1,26 @@
|
|||
name: PR Checks (master)
|
||||
|
||||
# Updated to ensure "Run Go Tests" runs for pull requests as expected.
|
||||
# Key fix: the test_go job previously required github.event.review.state == 'approved'
|
||||
# which only exists on pull_request_review events. That prevented the job from
|
||||
# running for regular pull_request events (opened / synchronize / reopened).
|
||||
# New logic: run tests for pull_request events, and also allow running when a
|
||||
# pull_request_review is submitted with state == 'approved'.
|
||||
on:
|
||||
pull_request:
|
||||
types: [opened, synchronize, reopened]
|
||||
branches:
|
||||
- master
|
||||
pull_request_review:
|
||||
types: [submitted]
|
||||
branches:
|
||||
- master
|
||||
workflow_dispatch: {}
|
||||
|
||||
name: PR Checks (master)
|
||||
|
||||
jobs:
|
||||
check_docs:
|
||||
name: Check Docs
|
||||
if: ${{github.repository == 'wailsapp/wails' && github.base_ref == 'master'}}
|
||||
if: ${{ github.repository == 'wailsapp/wails' && github.base_ref == 'master' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
|
|
@ -23,7 +32,6 @@ jobs:
|
|||
files: |
|
||||
website/**/*.mdx
|
||||
website/**/*.md
|
||||
|
||||
- name: Run step only when files change.
|
||||
if: steps.verify-changed-files.outputs.files_changed != 'true'
|
||||
run: |
|
||||
|
|
@ -32,11 +40,18 @@ jobs:
|
|||
test_go:
|
||||
name: Run Go Tests
|
||||
runs-on: ${{ matrix.os }}
|
||||
# Run when:
|
||||
# - the event is a pull_request (opened/synchronize/reopened) OR
|
||||
# - the event is a pull_request_review AND the review state is 'approved'
|
||||
# plus other existing filters (not the update-sponsors branch, repo and base_ref)
|
||||
if: >
|
||||
github.event.review.state == 'approved' &&
|
||||
github.repository == 'wailsapp/wails' &&
|
||||
github.repository == 'wailsapp/wails' &&
|
||||
github.base_ref == 'master' &&
|
||||
github.event.pull_request.head.ref != 'update-sponsors'
|
||||
github.event.pull_request.head.ref != 'update-sponsors' &&
|
||||
(
|
||||
github.event_name == 'pull_request' ||
|
||||
(github.event_name == 'pull_request_review' && github.event.review.state == 'approved')
|
||||
)
|
||||
strategy:
|
||||
matrix:
|
||||
os: [ubuntu-22.04, windows-latest, macos-latest, ubuntu-24.04]
|
||||
|
|
@ -52,7 +67,7 @@ jobs:
|
|||
|
||||
- name: Install linux dependencies (24.04)
|
||||
if: matrix.os == 'ubuntu-24.04'
|
||||
run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev libwayland-dev build-essential pkg-config
|
||||
run: sudo apt-get update -y && sudo apt-get install -y libgtk-3-dev libwebkit2gtk-4.1-dev build-essential pkg-config
|
||||
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v3
|
||||
|
|
@ -75,3 +90,15 @@ jobs:
|
|||
if: matrix.os == 'ubuntu-24.04'
|
||||
working-directory: ./v2
|
||||
run: go test -v -tags webkit2_41 ./...
|
||||
|
||||
# This job will run instead of test_go for the update-sponsors branch
|
||||
skip_tests:
|
||||
name: Skip Tests (Sponsor Update)
|
||||
if: github.event.pull_request.head.ref == 'update-sponsors'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Skip tests for sponsor updates
|
||||
run: |
|
||||
echo "Skipping tests for sponsor update branch"
|
||||
echo "This is an automated update of the sponsors image."
|
||||
continue-on-error: true
|
||||
|
|
|
|||
119
.github/workflows/publish-npm.yml
vendored
|
|
@ -1,119 +0,0 @@
|
|||
on:
|
||||
push:
|
||||
branches: ['v3-alpha']
|
||||
workflow_dispatch:
|
||||
|
||||
concurrency:
|
||||
group: publish-npm-v3
|
||||
cancel-in-progress: true
|
||||
|
||||
jobs:
|
||||
detect:
|
||||
name: Detect committed changes
|
||||
if: github.event_name != 'workflow_dispatch'
|
||||
outputs:
|
||||
changed: ${{ steps.package-json-changes.outputs.any_modified == 'true' || steps.source-changes.outputs.any_modified == 'true' }}
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
ref: ${{ github.sha }}
|
||||
persist-credentials: 'true'
|
||||
|
||||
- name: Detect committed package.json changes
|
||||
id: package-json-changes
|
||||
uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1
|
||||
with:
|
||||
files: |
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/package.json
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/package-lock.json
|
||||
|
||||
- name: Detect committed source changes
|
||||
if: >-
|
||||
steps.package-json-changes.outputs.any_modified != 'true'
|
||||
id: source-changes
|
||||
uses: step-security/changed-files@3dbe17c78367e7d60f00d78ae6781a35be47b4a1 # v45.0.1
|
||||
with:
|
||||
files: |
|
||||
v3/internal/runtime/Taskfile.yaml
|
||||
v3/internal/runtime/desktop/@wailsio/compiled/main.js
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/tsconfig.json
|
||||
v3/internal/runtime/desktop/@wailsio/runtime/src/**
|
||||
v3/pkg/events/events.txt
|
||||
v3/tasks/events/**
|
||||
|
||||
rebuild_and_publish:
|
||||
name: Rebuild and publish
|
||||
needs: [detect]
|
||||
if: >-
|
||||
!failure() && !cancelled()
|
||||
&& (github.event_name == 'workflow_dispatch' || needs.detect.outputs.changed == 'true')
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
actions: read
|
||||
pull-requests: read
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
ref: 'v3-alpha'
|
||||
token: ${{ secrets.WAILS_REPO_TOKEN || github.token }}
|
||||
|
||||
- name: Configure git
|
||||
run: |
|
||||
git config --global user.email "github-actions@github.com"
|
||||
git config --global user.name "GitHub Actions"
|
||||
git config --global url."https://x-access-token:${{ secrets.WAILS_REPO_TOKEN || github.token }}@github.com/".insteadOf "https://github.com/"
|
||||
|
||||
- name: Install Task
|
||||
uses: arduino/setup-task@v2
|
||||
with:
|
||||
version: 3.x
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Use Node.js 20
|
||||
uses: actions/setup-node@v4
|
||||
with:
|
||||
node-version: "20"
|
||||
|
||||
- name: Install dependencies
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: |
|
||||
npm ci
|
||||
npx --yes esbuild@latest --version
|
||||
|
||||
- name: Clean build artifacts
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: npm run clean
|
||||
|
||||
- name: Build bundled runtime
|
||||
working-directory: v3
|
||||
run: task runtime:build
|
||||
|
||||
- name: Test+Build npm package
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: |
|
||||
npm test
|
||||
npm run build
|
||||
|
||||
- name: Bump version
|
||||
id: bump-version
|
||||
working-directory: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
run: |
|
||||
echo "version=$(npm --no-git-tag-version --force version prerelease)" >> "$GITHUB_OUTPUT"
|
||||
|
||||
- name: Commit changes
|
||||
run: |
|
||||
git add .
|
||||
git commit -m "[skip ci] Publish @wailsio/runtime ${{ steps.bump-version.outputs.version }}"
|
||||
git push
|
||||
|
||||
- name: Publish npm package
|
||||
uses: JS-DevTools/npm-publish@v3
|
||||
with:
|
||||
package: v3/internal/runtime/desktop/@wailsio/runtime
|
||||
access: public
|
||||
token: ${{ secrets.NPM_TOKEN }}
|
||||
2
.github/workflows/test-nightly-releases.yml
vendored
|
|
@ -1,6 +1,4 @@
|
|||
name: Test Nightly Releases (Dry Run)
|
||||
permissions:
|
||||
contents: read
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
|
|
|||
11
.github/workflows/test-simple.yml
vendored
|
|
@ -1,11 +0,0 @@
|
|||
name: Test Simple
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
|
||||
jobs:
|
||||
test:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Test
|
||||
run: echo "Hello World"
|
||||
|
|
@ -39,6 +39,7 @@ jobs:
|
|||
name: Trigger v3-alpha Release
|
||||
permissions:
|
||||
contents: read
|
||||
actions: write
|
||||
runs-on: ubuntu-latest
|
||||
needs: check-permissions
|
||||
if: needs.check-permissions.outputs.authorized == 'true'
|
||||
|
|
|
|||
51
.github/workflows/v3-docs.yml
vendored
|
|
@ -1,51 +0,0 @@
|
|||
name: Deploy to GitHub Pages
|
||||
|
||||
on:
|
||||
# Trigger the workflow every time you push to the `main` branch
|
||||
# Using a different branch name? Replace `main` with your branch's name
|
||||
push:
|
||||
branches: [v3-alpha]
|
||||
paths:
|
||||
- 'docs/**'
|
||||
- '.github/workflows/v3-docs.yml'
|
||||
# Allows you to run this workflow manually from the Actions tab on GitHub.
|
||||
workflow_dispatch:
|
||||
|
||||
# Allow this job to clone the repo and create a page deployment
|
||||
permissions:
|
||||
contents: read
|
||||
pages: write
|
||||
id-token: write
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
if: github.event.repository.fork == false
|
||||
steps:
|
||||
- name: Checkout your repository using git
|
||||
uses: actions/checkout@v4
|
||||
- name: Install D2
|
||||
run: |
|
||||
curl -fsSL https://d2lang.com/install.sh > install.sh
|
||||
chmod +x install.sh
|
||||
./install.sh
|
||||
sudo cp ~/.local/bin/d2 /usr/local/bin/d2
|
||||
d2 --version
|
||||
rm install.sh
|
||||
- name: Install, build, and upload your site output
|
||||
uses: withastro/action@v2
|
||||
with:
|
||||
path: docs
|
||||
node-version: 20 # The specific version of Node that should be used to build your site. Defaults to 18. (optional)
|
||||
# package-manager: pnpm@latest # The Node package manager that should be used to install dependencies and build your site. Automatically detected based on your lockfile. (optional)
|
||||
|
||||
deploy:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
environment:
|
||||
name: github-pages
|
||||
url: ${{ steps.deployment.outputs.page_url }}
|
||||
steps:
|
||||
- name: Deploy to GitHub Pages
|
||||
id: deployment
|
||||
uses: actions/deploy-pages@v4
|
||||
58
.gitignore
vendored
|
|
@ -37,61 +37,5 @@ v2/cmd/wails/internal/commands/initialise/templates/testtemplates/
|
|||
/websitev3/site/
|
||||
/v3/examples/plugins/bin/testapp
|
||||
|
||||
# V3 Example binaries - ignore executables that match directory names
|
||||
/v3/examples/badge-custom/badge-custom
|
||||
/v3/examples/badge/badge
|
||||
/v3/examples/binding/binding
|
||||
/v3/examples/cancel-async/cancel-async
|
||||
/v3/examples/cancel-chaining/cancel-chaining
|
||||
/v3/examples/clipboard/clipboard
|
||||
/v3/examples/contextmenus/contextmenus
|
||||
/v3/examples/dev/dev
|
||||
/v3/examples/dialogs-basic/dialogs-basic
|
||||
/v3/examples/dialogs/dialogs
|
||||
/v3/examples/drag-n-drop/drag-n-drop
|
||||
/v3/examples/environment/environment
|
||||
/v3/examples/events-bug/events-bug
|
||||
/v3/examples/events/events
|
||||
/v3/examples/file-association/file-association
|
||||
/v3/examples/frameless/frameless
|
||||
/v3/examples/gin-example/gin-example
|
||||
/v3/examples/gin-routing/gin-routing
|
||||
/v3/examples/gin-service/gin-service
|
||||
/v3/examples/hide-window/hide-window
|
||||
/v3/examples/html-dnd-api/html-dnd-api
|
||||
/v3/examples/ignore-mouse/ignore-mouse
|
||||
/v3/examples/keybindings/keybindings
|
||||
/v3/examples/menu/menu
|
||||
/v3/examples/notifications/notifications
|
||||
/v3/examples/panic-handling/panic-handling
|
||||
/v3/examples/plain/plain
|
||||
/v3/examples/raw-message/raw-message
|
||||
/v3/examples/screen/screen
|
||||
/v3/examples/services/services
|
||||
/v3/examples/show-macos-toolbar/show-macos-toolbar
|
||||
/v3/examples/single-instance/single-instance
|
||||
/v3/examples/systray-basic/systray-basic
|
||||
/v3/examples/systray-custom/systray-custom
|
||||
/v3/examples/systray-menu/systray-menu
|
||||
/v3/examples/video/video
|
||||
/v3/examples/window-api/window-api
|
||||
/v3/examples/window-call/window-call
|
||||
/v3/examples/window-menu/window-menu
|
||||
/v3/examples/window/window
|
||||
/v3/examples/wml/wml
|
||||
|
||||
# Common binary names in examples
|
||||
/v3/examples/*/main
|
||||
/v3/examples/*/app
|
||||
/v3/examples/*/changeme
|
||||
/v3/examples/*/testbuild-*
|
||||
|
||||
# Temporary called mkdocs, should be renamed to more standard -website or similar
|
||||
/docs/site
|
||||
.aider*
|
||||
.aider*
|
||||
.cache
|
||||
.local
|
||||
|
||||
# Ignore local iOS test app
|
||||
/v3/testiosapp/
|
||||
/mkdocs-website/site
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
overrides:
|
||||
- files:
|
||||
- "**/*.md"
|
||||
- "**/*.mdx"
|
||||
options:
|
||||
printWidth: 80
|
||||
proseWrap: always
|
||||
|
|
|
|||
8
.replit
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
modules = ["go-1.21", "web", "nodejs-20"]
|
||||
run = "go run v2/cmd/wails/main.go"
|
||||
|
||||
[nix]
|
||||
channel = "stable-24_05"
|
||||
|
||||
[deployment]
|
||||
run = ["sh", "-c", "go run v2/cmd/wails/main.go"]
|
||||
197
AGENTS.md
|
|
@ -1,197 +0,0 @@
|
|||
# AI Agent Instructions for Wails v3
|
||||
|
||||
## Issue Tracking with bd (beads)
|
||||
|
||||
**IMPORTANT**: This project uses **bd (beads)** for ALL issue tracking. Do NOT use markdown TODOs, task lists, or other tracking methods.
|
||||
|
||||
### Why bd?
|
||||
|
||||
- Dependency-aware: Track blockers and relationships between issues
|
||||
- Git-friendly: Auto-syncs to JSONL for version control
|
||||
- Agent-optimized: JSON output, ready work detection, discovered-from links
|
||||
- Prevents duplicate tracking systems and confusion
|
||||
|
||||
### Quick Start
|
||||
|
||||
**Check for ready work:**
|
||||
```bash
|
||||
bd ready --json
|
||||
```
|
||||
|
||||
**Create new issues:**
|
||||
```bash
|
||||
bd create "Issue title" -t bug|feature|task -p 0-4 --json
|
||||
bd create "Issue title" -p 1 --deps discovered-from:bd-123 --json
|
||||
bd create "Subtask" --parent <epic-id> --json # Hierarchical subtask (gets ID like epic-id.1)
|
||||
```
|
||||
|
||||
**Claim and update:**
|
||||
```bash
|
||||
bd update bd-42 --status in_progress --json
|
||||
bd update bd-42 --priority 1 --json
|
||||
```
|
||||
|
||||
**Complete work:**
|
||||
```bash
|
||||
bd close bd-42 --reason "Completed" --json
|
||||
```
|
||||
|
||||
### Issue Types
|
||||
|
||||
- `bug` - Something broken
|
||||
- `feature` - New functionality
|
||||
- `task` - Work item (tests, docs, refactoring)
|
||||
- `epic` - Large feature with subtasks
|
||||
- `chore` - Maintenance (dependencies, tooling)
|
||||
|
||||
### Priorities
|
||||
|
||||
- `0` - Critical (security, data loss, broken builds)
|
||||
- `1` - High (major features, important bugs)
|
||||
- `2` - Medium (default, nice-to-have)
|
||||
- `3` - Low (polish, optimization)
|
||||
- `4` - Backlog (future ideas)
|
||||
|
||||
### Workflow for AI Agents
|
||||
|
||||
1. **Check ready work**: `bd ready` shows unblocked issues
|
||||
2. **Claim your task**: `bd update <id> --status in_progress`
|
||||
3. **Work on it**: Implement, test, document
|
||||
4. **Discover new work?** Create linked issue:
|
||||
- `bd create "Found bug" -p 1 --deps discovered-from:<parent-id>`
|
||||
5. **Complete**: `bd close <id> --reason "Done"`
|
||||
6. **Commit together**: Always commit the `.beads/issues.jsonl` file together with the code changes so issue state stays in sync with code state
|
||||
|
||||
### Auto-Sync
|
||||
|
||||
bd automatically syncs with git:
|
||||
- Exports to `.beads/issues.jsonl` after changes (5s debounce)
|
||||
- Imports from JSONL when newer (e.g., after `git pull`)
|
||||
- No manual export/import needed!
|
||||
|
||||
### GitHub Copilot Integration
|
||||
|
||||
If using GitHub Copilot, also create `.github/copilot-instructions.md` for automatic instruction loading.
|
||||
Run `bd onboard` to get the content, or see step 2 of the onboard instructions.
|
||||
|
||||
### MCP Server (Recommended)
|
||||
|
||||
If using Claude or MCP-compatible clients, install the beads MCP server:
|
||||
|
||||
```bash
|
||||
pip install beads-mcp
|
||||
```
|
||||
|
||||
Add to MCP config (e.g., `~/.config/claude/config.json`):
|
||||
```json
|
||||
{
|
||||
"beads": {
|
||||
"command": "beads-mcp",
|
||||
"args": []
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Then use `mcp__beads__*` functions instead of CLI commands.
|
||||
|
||||
### Managing AI-Generated Planning Documents
|
||||
|
||||
AI assistants often create planning and design documents during development:
|
||||
- PLAN.md, IMPLEMENTATION.md, ARCHITECTURE.md
|
||||
- DESIGN.md, CODEBASE_SUMMARY.md, INTEGRATION_PLAN.md
|
||||
- TESTING_GUIDE.md, TECHNICAL_DESIGN.md, and similar files
|
||||
|
||||
**Best Practice: Use a dedicated directory for these ephemeral files**
|
||||
|
||||
**Recommended approach:**
|
||||
- Create a `history/` directory in the project root
|
||||
- Store ALL AI-generated planning/design docs in `history/`
|
||||
- Keep the repository root clean and focused on permanent project files
|
||||
- Only access `history/` when explicitly asked to review past planning
|
||||
|
||||
**Example .gitignore entry (optional):**
|
||||
```
|
||||
# AI planning documents (ephemeral)
|
||||
history/
|
||||
```
|
||||
|
||||
**Benefits:**
|
||||
- Clean repository root
|
||||
- Clear separation between ephemeral and permanent documentation
|
||||
- Easy to exclude from version control if desired
|
||||
- Preserves planning history for archeological research
|
||||
- Reduces noise when browsing the project
|
||||
|
||||
### CLI Help
|
||||
|
||||
Run `bd <command> --help` to see all available flags for any command.
|
||||
For example: `bd create --help` shows `--parent`, `--deps`, `--assignee`, etc.
|
||||
|
||||
### Important Rules
|
||||
|
||||
- Use bd for ALL task tracking
|
||||
- Always use `--json` flag for programmatic use
|
||||
- Link discovered work with `discovered-from` dependencies
|
||||
- Check `bd ready` before asking "what should I work on?"
|
||||
- Store AI planning docs in `history/` directory
|
||||
- Run `bd <cmd> --help` to discover available flags
|
||||
- **ALWAYS run `coderabbit --plain` before committing** to get code analysis and catch issues early
|
||||
- Do NOT create markdown TODO lists
|
||||
- Do NOT use external issue trackers
|
||||
- Do NOT duplicate tracking systems
|
||||
- Do NOT clutter repo root with planning documents
|
||||
|
||||
For more details, see README.md and QUICKSTART.md.
|
||||
|
||||
## Implementation Tracking (IMPLEMENTATION.md)
|
||||
|
||||
**IMPORTANT**: The `IMPLEMENTATION.md` file at the repository root is a **persistent tracking document** for the WebKitGTK 6.0 / GTK4 implementation work. It is NOT an ephemeral planning document.
|
||||
|
||||
### Requirements
|
||||
|
||||
1. **Update with EVERY commit** that touches GTK4/WebKitGTK 6.0 related code
|
||||
2. **Track all architectural decisions** with context, decision, and rationale
|
||||
3. **Maintain progress status** for each implementation phase
|
||||
4. **Document API differences** between GTK3 and GTK4
|
||||
5. **Keep file references** accurate and up-to-date
|
||||
|
||||
### What to Update
|
||||
|
||||
- Phase completion status (✅ COMPLETE, 🔄 IN PROGRESS, 📋 PENDING)
|
||||
- New decisions made during implementation
|
||||
- Files created or modified
|
||||
- Changelog entries with dates
|
||||
- TODO items discovered during work
|
||||
|
||||
### Commit Message Pattern
|
||||
|
||||
When updating IMPLEMENTATION.md:
|
||||
```
|
||||
docs: update implementation tracker for [phase/feature]
|
||||
```
|
||||
|
||||
## Landing the Plane (Session Completion)
|
||||
|
||||
**When ending a work session**, you MUST complete ALL steps below. Work is NOT complete until `git push` succeeds.
|
||||
|
||||
**MANDATORY WORKFLOW:**
|
||||
|
||||
1. **File issues for remaining work** - Create issues for anything that needs follow-up
|
||||
2. **Run quality gates** (if code changed) - Tests, linters, builds
|
||||
3. **Update issue status** - Close finished work, update in-progress items
|
||||
4. **PUSH TO REMOTE** - This is MANDATORY:
|
||||
```bash
|
||||
git pull --rebase
|
||||
bd sync
|
||||
git push
|
||||
git status # MUST show "up to date with origin"
|
||||
```
|
||||
5. **Clean up** - Clear stashes, prune remote branches
|
||||
6. **Verify** - All changes committed AND pushed
|
||||
7. **Hand off** - Provide context for next session
|
||||
|
||||
**CRITICAL RULES:**
|
||||
- Work is NOT complete until `git push` succeeds
|
||||
- NEVER stop before pushing - that leaves work stranded locally
|
||||
- NEVER say "ready to push when you are" - YOU must push
|
||||
- If push fails, resolve and retry until it succeeds
|
||||
1
CNAME
|
|
@ -1 +0,0 @@
|
|||
v3alpha.wails.io
|
||||
|
|
@ -1,543 +0,0 @@
|
|||
# WebKitGTK 6.0 / GTK4 Implementation Tracker
|
||||
|
||||
## Overview
|
||||
|
||||
This document tracks the implementation of WebKitGTK 6.0 (GTK4) support for Wails v3 on Linux.
|
||||
|
||||
**Goal**: Provide GTK4/WebKitGTK 6.0 support as an EXPERIMENTAL opt-in via `-tags gtk4`, while maintaining GTK3/WebKit2GTK 4.1 as the stable default.
|
||||
|
||||
## Architecture Decisions
|
||||
|
||||
### Decision 1: GTK3 as Default, GTK4 Opt-In (2026-02-04)
|
||||
**Context**: Need to support modern Linux distributions with GTK4 while maintaining stability for existing apps.
|
||||
|
||||
**Decision**: GTK3 remains the stable default (no build tag required). GTK4 is available as experimental via `-tags gtk4`.
|
||||
|
||||
**Rationale**:
|
||||
- GTK3/WebKit2GTK 4.1 is battle-tested and widely deployed
|
||||
- GTK4 support needs more community testing before becoming default
|
||||
- Allows gradual migration and feedback collection
|
||||
- Protects existing apps from unexpected breakage
|
||||
|
||||
**Build Tags**:
|
||||
- Default (no tag): `//go:build linux && cgo && !gtk4 && !android`
|
||||
- Experimental GTK4: `//go:build linux && cgo && gtk4 && !android`
|
||||
|
||||
### Decision 2: pkg-config Libraries (2026-01-04)
|
||||
**GTK4/WebKitGTK 6.0**:
|
||||
```
|
||||
#cgo linux pkg-config: gtk4 webkitgtk-6.0 libsoup-3.0
|
||||
```
|
||||
|
||||
**GTK3/WebKit2GTK 4.1** (legacy):
|
||||
```
|
||||
#cgo linux pkg-config: gtk+-3.0 webkit2gtk-4.1 libsoup-3.0
|
||||
```
|
||||
|
||||
### Decision 3: Wayland Window Positioning (2026-01-04)
|
||||
**Context**: GTK4/Wayland doesn't support arbitrary window positioning - this is a Wayland protocol limitation.
|
||||
|
||||
**Decision**: Window positioning functions (`move()`, `setPosition()`, `center()`) are documented NO-OPs on GTK4/Wayland.
|
||||
|
||||
**Rationale**: This is a fundamental Wayland design decision, not a limitation we can work around. Users need to be aware of this behavioral difference.
|
||||
|
||||
### Decision 4: Menu System Architecture (2026-01-04)
|
||||
**Context**: GTK4 removes GtkMenu/GtkMenuItem in favor of GMenu/GAction.
|
||||
|
||||
**Decision**: Complete rewrite of menu system for GTK4 using GMenu/GAction/GtkPopoverMenuBar.
|
||||
|
||||
**Status**: Stub implementations only. Full implementation pending.
|
||||
|
||||
### Decision 5: System Tray Compatibility (2026-01-04)
|
||||
**Context**: v3's system tray uses D-Bus StatusNotifierItem protocol.
|
||||
|
||||
**Decision**: No changes needed - system tray is already GTK-agnostic.
|
||||
|
||||
## Implementation Progress
|
||||
|
||||
### Phase 1: Build Infrastructure ✅ COMPLETE
|
||||
|
||||
**Commit**: `a0ca13fdc` (2026-01-04)
|
||||
|
||||
#### 1.1 Add gtk3 constraint to existing files
|
||||
Files modified:
|
||||
- `v3/pkg/application/application_linux.go` - Added `gtk3` constraint
|
||||
- `v3/pkg/application/linux_cgo.go` - Added `gtk3` constraint
|
||||
- `v3/internal/assetserver/webview/request_linux.go` - Added `gtk3` constraint
|
||||
- `v3/internal/assetserver/webview/responsewriter_linux.go` - Added `gtk3` constraint
|
||||
- `v3/internal/assetserver/webview/webkit2.go` - Added `gtk3` constraint
|
||||
|
||||
#### 1.2 Create GTK4 stub files
|
||||
Files created:
|
||||
- `v3/pkg/application/linux_cgo_gtk4.go` (~1000 lines)
|
||||
- Main CGO file with GTK4 bindings
|
||||
- Implements: window management, clipboard, basic menu stubs
|
||||
- Uses `gtk4 webkitgtk-6.0` pkg-config
|
||||
|
||||
- `v3/pkg/application/application_linux_gtk4.go` (~250 lines)
|
||||
- Application lifecycle management
|
||||
- System theme detection via D-Bus
|
||||
- NVIDIA DMA-BUF workaround for Wayland
|
||||
|
||||
#### 1.3 Create WebKitGTK 6.0 asset server stubs
|
||||
Files created:
|
||||
- `v3/internal/assetserver/webview/webkit6.go`
|
||||
- `v3/internal/assetserver/webview/request_linux_gtk4.go`
|
||||
- `v3/internal/assetserver/webview/responsewriter_linux_gtk4.go`
|
||||
|
||||
### Phase 2: Doctor & Capabilities ✅ COMPLETE
|
||||
|
||||
**Goal**: Update `wails doctor` to check for GTK4 as primary, GTK3 as secondary.
|
||||
|
||||
#### 2.1 Package Manager Updates
|
||||
All 7 package managers updated to check GTK4/WebKitGTK 6.0 as primary, GTK3 as optional/legacy:
|
||||
- `v3/internal/doctor/packagemanager/apt.go` ✅
|
||||
- `v3/internal/doctor/packagemanager/dnf.go` ✅
|
||||
- `v3/internal/doctor/packagemanager/pacman.go` ✅
|
||||
- `v3/internal/doctor/packagemanager/zypper.go` ✅
|
||||
- `v3/internal/doctor/packagemanager/emerge.go` ✅
|
||||
- `v3/internal/doctor/packagemanager/eopkg.go` ✅
|
||||
- `v3/internal/doctor/packagemanager/nixpkgs.go` ✅
|
||||
|
||||
Package key naming convention: `gtk3`, `webkit2gtk-4.1` (primary/default), `gtk4`, `webkitgtk-6.0` (experimental, optional)
|
||||
|
||||
#### 2.2 Capabilities Detection
|
||||
Files created/updated:
|
||||
- `v3/internal/capabilities/capabilities.go` - Added `GTKVersion` (int) and `WebKitVersion` (string) fields
|
||||
- `v3/internal/capabilities/capabilities_linux.go` - GTK4 default: `GTKVersion: 4, WebKitVersion: "6.0"`
|
||||
- `v3/internal/capabilities/capabilities_linux_gtk3.go` - GTK3 legacy: `GTKVersion: 3, WebKitVersion: "4.1"`
|
||||
|
||||
TODO (deferred to Phase 3):
|
||||
- [ ] Update `v3/internal/doctor/doctor_linux.go` - Improve output to show GTK4 vs GTK3 status
|
||||
|
||||
### Phase 3: Window Management ✅ COMPLETE
|
||||
|
||||
#### 3.1 GTK4 Event Controllers
|
||||
GTK4 replaces direct signal handlers with `GtkEventController` objects:
|
||||
- `GtkEventControllerFocus` for focus in/out events
|
||||
- `GtkGestureClick` for button press/release events
|
||||
- `GtkEventControllerKey` for keyboard events
|
||||
- Window signals: `close-request`, `notify::maximized`, `notify::fullscreened`
|
||||
|
||||
New C function `setupWindowEventControllers()` sets up all event controllers.
|
||||
|
||||
#### 3.2 Window Drag and Resize
|
||||
GTK4 uses `GdkToplevel` API instead of GTK3's `gtk_window_begin_move_drag`:
|
||||
- `gdk_toplevel_begin_move()` for window drag
|
||||
- `gdk_toplevel_begin_resize()` for window resize
|
||||
- Requires `gtk_native_get_surface()` to get the GdkSurface
|
||||
|
||||
#### 3.3 Drag-and-Drop with GtkDropTarget
|
||||
Complete implementation using GTK4's `GtkDropTarget`:
|
||||
- `on_drop_enter` / `on_drop_leave` for drag enter/exit events
|
||||
- `on_drop_motion` for drag position updates
|
||||
- `on_drop` handles file drops via `GDK_TYPE_FILE_LIST`
|
||||
- Go callbacks: `onDropEnter`, `onDropLeave`, `onDropMotion`, `onDropFiles`
|
||||
|
||||
#### 3.4 Window State Detection
|
||||
- `isMinimised()` uses `gdk_toplevel_get_state()` with `GDK_TOPLEVEL_STATE_MINIMIZED`
|
||||
- `isMaximised()` uses `gtk_window_is_maximized()`
|
||||
- `isFullscreen()` uses `gtk_window_is_fullscreen()`
|
||||
|
||||
#### 3.5 Size Constraints
|
||||
GTK4 removed `gtk_window_set_geometry_hints()`. Now using `gtk_widget_set_size_request()` for minimum size.
|
||||
|
||||
TODO (deferred):
|
||||
- [ ] Test window lifecycle on GTK4 with actual GTK4 libraries
|
||||
|
||||
### Phase 4: Menu System ✅ COMPLETE
|
||||
|
||||
GTK4 completely replaced the menu system. GTK3's GtkMenu/GtkMenuItem are gone.
|
||||
|
||||
#### 4.1 GMenu/GAction Architecture
|
||||
- `GMenu` - Menu model (data structure, not a widget)
|
||||
- `GMenuItem` - Individual menu item in the model
|
||||
- `GSimpleAction` - Action that gets triggered when menu item is activated
|
||||
- `GSimpleActionGroup` - Container for actions, attached to widgets
|
||||
|
||||
#### 4.2 Menu Bar Implementation
|
||||
- `GtkPopoverMenuBar` created from `GMenu` model via `create_menu_bar_from_model()`
|
||||
- Action group attached to window with `attach_action_group_to_widget()`
|
||||
- Actions use "app.action_name" namespace
|
||||
|
||||
#### 4.3 New Files Created
|
||||
- `v3/pkg/application/menu_linux_gtk4.go` - GTK4 menu processing
|
||||
- `v3/pkg/application/menuitem_linux_gtk4.go` - GTK4 menu item handling
|
||||
|
||||
#### 4.4 Build Tag Changes
|
||||
- `menu_linux.go` - Added `gtk3` tag
|
||||
- `menuitem_linux.go` - Added `gtk3` tag
|
||||
|
||||
#### 4.5 Key Functions
|
||||
- `menuActionActivated()` - Callback when GAction is triggered
|
||||
- `menuItemNewWithId()` - Creates GMenuItem + associated GSimpleAction
|
||||
- `menuCheckItemNewWithId()` - Creates stateful toggle action
|
||||
- `menuRadioItemNewWithId()` - Creates radio action
|
||||
- `set_action_enabled()` / `set_action_state()` - Manage action state
|
||||
|
||||
TODO (deferred):
|
||||
- [ ] Context menus with GtkPopoverMenu
|
||||
|
||||
### Phase 5: Asset Server ✅ COMPLETE
|
||||
|
||||
WebKitGTK 6.0 uses the same URI scheme handler API as WebKitGTK 4.1.
|
||||
The asset server implementation is identical between GTK3 and GTK4.
|
||||
|
||||
#### 5.1 Asset Server Files (already created in Phase 1)
|
||||
- `v3/internal/assetserver/webview/webkit6.go` - WebKitGTK 6.0 helpers
|
||||
- `v3/internal/assetserver/webview/request_linux_gtk4.go` - Request handling
|
||||
- `v3/internal/assetserver/webview/responsewriter_linux_gtk4.go` - Response writing
|
||||
|
||||
#### 5.2 Missing Exports Added
|
||||
The GTK4 CGO file was missing two critical exports that were in the GTK3 file:
|
||||
- `onProcessRequest` - Handles URI scheme requests from WebKit
|
||||
- `sendMessageToBackend` - Handles JavaScript to Go communication
|
||||
|
||||
Both exports were added to `linux_cgo_gtk4.go`.
|
||||
|
||||
#### 5.3 Key Differences from GTK3
|
||||
| Aspect | GTK3 | GTK4 |
|
||||
|--------|------|------|
|
||||
| pkg-config | `webkit2gtk-4.1` | `webkitgtk-6.0` |
|
||||
| Headers | `webkit2/webkit2.h` | `webkit/webkit.h` |
|
||||
| Min version | 2.40 | 6.0 |
|
||||
| URI scheme API | Same | Same |
|
||||
|
||||
TODO (deferred to testing phase):
|
||||
- [ ] Test asset loading on actual GTK4 system
|
||||
- [ ] Verify JavaScript execution works correctly
|
||||
|
||||
### Phase 6: Docker & Build System ✅ COMPLETE
|
||||
|
||||
#### 6.1 Docker Container Updates
|
||||
Updated both Dockerfile.linux-x86_64 and Dockerfile.linux-arm64 to install:
|
||||
- GTK3 + WebKit2GTK 4.1 (default build target)
|
||||
- GTK4 + WebKitGTK 6.0 (for experimental `-tags gtk4` builds)
|
||||
|
||||
Build scripts now support `BUILD_TAGS` environment variable:
|
||||
- Default: Builds with GTK3/WebKit2GTK 4.1
|
||||
- `BUILD_TAGS=gtk4`: Builds with GTK4/WebKitGTK 6.0 (experimental)
|
||||
|
||||
#### 6.2 Taskfile Targets
|
||||
New targets added to `v3/Taskfile.yaml`:
|
||||
|
||||
| Target | Description |
|
||||
|--------|-------------|
|
||||
| `test:example:linux` | Build single example with GTK3 (native, default) |
|
||||
| `test:example:linux:gtk4` | Build single example with GTK4 (native, experimental) |
|
||||
| `test:examples:linux:docker:x86_64` | Build all examples with GTK3 in Docker |
|
||||
| `test:examples:linux:docker:x86_64:gtk4` | Build all examples with GTK4 in Docker (experimental) |
|
||||
| `test:examples:linux:docker:arm64` | Build all examples with GTK3 in Docker (ARM64) |
|
||||
| `test:examples:linux:docker:arm64:gtk4` | Build all examples with GTK4 in Docker (ARM64, experimental) |
|
||||
|
||||
TODO (deferred):
|
||||
- [ ] Update CI/CD workflows to test both GTK versions
|
||||
|
||||
### Phase 8: Dialog System ✅ COMPLETE
|
||||
|
||||
GTK4 completely replaced the dialog APIs. GTK3's `GtkFileChooserDialog` and
|
||||
`gtk_message_dialog_new` are deprecated/removed.
|
||||
|
||||
#### 8.1 File Dialogs
|
||||
GTK4 uses `GtkFileDialog` with async API:
|
||||
- `gtk_file_dialog_open()` - Open single file
|
||||
- `gtk_file_dialog_open_multiple()` - Open multiple files
|
||||
- `gtk_file_dialog_select_folder()` - Select folder
|
||||
- `gtk_file_dialog_select_multiple_folders()` - Select multiple folders
|
||||
- `gtk_file_dialog_save()` - Save file
|
||||
|
||||
Key differences:
|
||||
- No more `gtk_dialog_run()` - everything is async with callbacks
|
||||
- Filters use `GListStore` of `GtkFileFilter` objects
|
||||
- Results delivered via `GAsyncResult` callbacks
|
||||
- Custom button text via `gtk_file_dialog_set_accept_label()`
|
||||
|
||||
#### 8.1.1 GTK4 File Dialog Limitations (Portal-based)
|
||||
|
||||
GTK4's `GtkFileDialog` uses **xdg-desktop-portal** for native file dialogs. This provides
|
||||
better desktop integration but removes some application control:
|
||||
|
||||
| Feature | GTK3 | GTK4 | Notes |
|
||||
|---------|------|------|-------|
|
||||
| `ShowHiddenFiles()` | ✅ Works | ❌ No effect | User controls via portal UI toggle |
|
||||
| `CanCreateDirectories()` | ✅ Works | ❌ No effect | Always enabled in portal |
|
||||
| `ResolvesAliases()` | ✅ Works | ❌ No effect | Portal handles symlinks |
|
||||
| `SetButtonText()` | ✅ Works | ✅ Works | `gtk_file_dialog_set_accept_label()` |
|
||||
| Multiple folders | ✅ Works | ✅ Works | `gtk_file_dialog_select_multiple_folders()` |
|
||||
|
||||
**Why these limitations exist**: GTK4's portal-based dialogs delegate UI control to the
|
||||
desktop environment (GNOME, KDE, etc.). This is intentional - the portal provides
|
||||
consistent UX across applications and respects user preferences.
|
||||
|
||||
#### 8.2 Message Dialogs
|
||||
GTK4 uses `GtkAlertDialog`:
|
||||
- `gtk_alert_dialog_choose()` - Show dialog with buttons
|
||||
- Buttons specified as NULL-terminated string array
|
||||
- Default and cancel button indices configurable
|
||||
|
||||
#### 8.3 Implementation Details
|
||||
- Request ID tracking for async callback matching
|
||||
- `fileDialogCallback` / `alertDialogCallback` C exports for results
|
||||
- `runChooserDialog()` and `runQuestionDialog()` Go wrappers
|
||||
- `runOpenFileDialog()` and `runSaveFileDialog()` convenience functions
|
||||
|
||||
| GTK3 | GTK4 |
|
||||
|------|------|
|
||||
| `GtkFileChooserDialog` | `GtkFileDialog` |
|
||||
| `gtk_dialog_run()` | Async callbacks |
|
||||
| `gtk_message_dialog_new()` | `GtkAlertDialog` |
|
||||
| `gtk_widget_destroy()` | `g_object_unref()` |
|
||||
|
||||
### Phase 9: Keyboard Accelerators ✅ COMPLETE
|
||||
|
||||
GTK4 uses `gtk_application_set_accels_for_action()` to bind keyboard shortcuts to GActions.
|
||||
|
||||
#### 9.1 Key Components
|
||||
|
||||
**C Helper Functions** (in `linux_cgo_gtk4.go`):
|
||||
- `set_action_accelerator(app, action_name, accel)` - Sets accelerator for a GAction
|
||||
- `build_accelerator_string(key, mods)` - Converts key+modifiers to GTK accelerator string
|
||||
|
||||
**Go Functions** (in `linux_cgo_gtk4.go`):
|
||||
- `namedKeysToGTK` - Map of key names to GDK keysym values (e.g., "backspace" → 0xff08)
|
||||
- `parseKeyGTK(key)` - Converts Wails key string to GDK keysym
|
||||
- `parseModifiersGTK(modifiers)` - Converts Wails modifiers to GdkModifierType
|
||||
- `acceleratorToGTK(accel)` - Converts full accelerator to GTK format
|
||||
- `setMenuItemAccelerator(itemId, accel)` - Sets accelerator for a menu item
|
||||
|
||||
**Integration** (in `menuitem_linux_gtk4.go`):
|
||||
- `setAccelerator()` method on `linuxMenuItem` calls `setMenuItemAccelerator()`
|
||||
- `newMenuItemImpl()`, `newCheckMenuItemImpl()`, `newRadioMenuItemImpl()` all set accelerators during creation
|
||||
|
||||
#### 9.2 Accelerator String Format
|
||||
|
||||
GTK accelerator strings use format like:
|
||||
- `<Control>q` - Ctrl+Q
|
||||
- `<Control><Shift>s` - Ctrl+Shift+S
|
||||
- `<Alt>F4` - Alt+F4
|
||||
- `<Super>e` - Super+E (Windows/Command key)
|
||||
|
||||
#### 9.3 Modifier Mapping
|
||||
|
||||
| Wails Modifier | GDK Modifier |
|
||||
|----------------|--------------|
|
||||
| `CmdOrCtrlKey` | `GDK_CONTROL_MASK` |
|
||||
| `ControlKey` | `GDK_CONTROL_MASK` |
|
||||
| `OptionOrAltKey` | `GDK_ALT_MASK` |
|
||||
| `ShiftKey` | `GDK_SHIFT_MASK` |
|
||||
| `SuperKey` | `GDK_SUPER_MASK` |
|
||||
|
||||
### Phase 10: Testing 📋 PENDING
|
||||
|
||||
TODO:
|
||||
- [ ] Test on Ubuntu 24.04 (native GTK4)
|
||||
- [ ] Test on Ubuntu 22.04 (backported WebKitGTK 6.0)
|
||||
- [ ] Test legacy build on older systems
|
||||
- [ ] Performance benchmarks
|
||||
- [ ] Verify file dialogs work correctly
|
||||
- [ ] Verify message dialogs work correctly
|
||||
|
||||
## API Differences: GTK3 vs GTK4
|
||||
|
||||
| Feature | GTK3 | GTK4 |
|
||||
|---------|------|------|
|
||||
| Init | `gtk_init(&argc, &argv)` | `gtk_init_check()` |
|
||||
| Container | `gtk_container_add()` | `gtk_window_set_child()` |
|
||||
| Show | `gtk_widget_show_all()` | Widgets visible by default |
|
||||
| Hide | `gtk_widget_hide()` | `gtk_widget_set_visible(w, FALSE)` |
|
||||
| Clipboard | `GtkClipboard` | `GdkClipboard` |
|
||||
| Menu | `GtkMenu/GtkMenuItem` | `GMenu/GAction` |
|
||||
| Menu Bar | `GtkMenuBar` | `GtkPopoverMenuBar` |
|
||||
| Window Move | `gtk_window_move()` | NO-OP on Wayland |
|
||||
| Window Position | `gtk_window_get_position()` | Not available on Wayland |
|
||||
| Destroy | `gtk_widget_destroy()` | `gtk_window_destroy()` |
|
||||
| Drag Start | `gtk_window_begin_move_drag()` | `gtk_native_get_surface()` + surface drag |
|
||||
|
||||
## Files Reference
|
||||
|
||||
### GTK3 (Default) Files
|
||||
```
|
||||
v3/pkg/application/
|
||||
linux_cgo.go # Main CGO (!gtk4 tag - default)
|
||||
application_linux.go # App lifecycle (!gtk4 tag - default)
|
||||
|
||||
v3/internal/assetserver/webview/
|
||||
webkit2.go # WebKit2GTK helpers (!gtk4 tag - default)
|
||||
request_linux.go # Request handling (!gtk4 tag - default)
|
||||
responsewriter_linux.go # Response writing (!gtk4 tag - default)
|
||||
|
||||
v3/internal/capabilities/
|
||||
capabilities_linux_gtk3.go # GTK3 capabilities (!gtk4 tag - default)
|
||||
|
||||
v3/internal/operatingsystem/
|
||||
webkit_linux.go # WebKit version info (!gtk4 tag - default)
|
||||
```
|
||||
|
||||
### GTK4 (Experimental) Files
|
||||
```
|
||||
v3/pkg/application/
|
||||
linux_cgo_gtk4.go # Main CGO (gtk4 tag - experimental)
|
||||
application_linux_gtk4.go # App lifecycle (gtk4 tag - experimental)
|
||||
|
||||
v3/internal/assetserver/webview/
|
||||
webkit6.go # WebKitGTK 6.0 helpers (gtk4 tag - experimental)
|
||||
request_linux_gtk4.go # Request handling (gtk4 tag - experimental)
|
||||
responsewriter_linux_gtk4.go # Response writing (gtk4 tag - experimental)
|
||||
|
||||
v3/internal/capabilities/
|
||||
capabilities_linux.go # GTK4 capabilities (gtk4 tag - experimental)
|
||||
|
||||
v3/internal/operatingsystem/
|
||||
webkit_linux_gtk4.go # WebKit version info (gtk4 tag - experimental)
|
||||
```
|
||||
|
||||
### Shared Files (no GTK-specific code)
|
||||
```
|
||||
v3/pkg/application/
|
||||
webview_window_linux.go # Window wrapper (uses methods from CGO files)
|
||||
systemtray_linux.go # D-Bus based, GTK-agnostic
|
||||
|
||||
v3/internal/assetserver/webview/
|
||||
request.go # Interface definitions
|
||||
responsewriter.go # Interface definitions
|
||||
```
|
||||
|
||||
## Changelog
|
||||
|
||||
### 2026-01-07 (Session 11)
|
||||
- Fixed GTK4 dialog system bugs
|
||||
- **File Dialog Fix**: Removed premature `g_object_unref()` that freed dialog before async callback
|
||||
- GTK4 async dialogs manage their own lifecycle
|
||||
- Commit: `6f9c5beb5`
|
||||
- **Alert Dialog Fixes**:
|
||||
- Removed premature `g_object_unref(dialog)` from `show_alert_dialog()` (same issue as file dialogs)
|
||||
- Fixed deadlock in `dialogs_linux.go` - `InvokeAsync` → `go func()` since `runQuestionDialog` blocks internally
|
||||
- Fixed `runQuestionDialog` to use `options.Title` as message (was using `options.Message`)
|
||||
- Added default "OK" button when no buttons specified
|
||||
- Commit: `1a77e6091`
|
||||
- **Other Fixes**:
|
||||
- Fixed checkptr errors with `-race` flag by changing C signal functions to accept `uintptr_t` (`3999f1f24`)
|
||||
- Fixed ExecJS race condition by adding mutex for `runtimeLoaded`/`pendingJS` (`8e386034e`)
|
||||
- Added DEBUG_LOG macro for compile-time debug output: `CGO_CFLAGS="-DWAILS_GTK_DEBUG" go build ...`
|
||||
- Added manual dialog test suite in `v3/test/manual/dialog/`
|
||||
- **Additional Dialog Fixes** (Session 11 continued):
|
||||
- Added `gtk_file_dialog_set_accept_label()` for custom button text
|
||||
- Added `gtk_file_dialog_select_multiple_folders()` for multiple directory selection
|
||||
- Fixed data race in `application.go` cleanup - was using RLock() when writing `a.windows = nil`
|
||||
- Documented GTK4 portal limitations (ShowHiddenFiles, CanCreateDirectories have no effect)
|
||||
- Files modified:
|
||||
- `v3/pkg/application/linux_cgo_gtk4.go` - dialog fixes, race fixes, accept label, multiple folders
|
||||
- `v3/pkg/application/linux_cgo_gtk4.c` - DEBUG_LOG macro, alert dialog lifecycle fix, select_multiple_folders callback
|
||||
- `v3/pkg/application/linux_cgo_gtk4.h` - uintptr_t for signal functions
|
||||
- `v3/pkg/application/dialogs_linux.go` - deadlock fix
|
||||
- `v3/pkg/application/webview_window.go` - pendingJS mutex
|
||||
- `v3/pkg/application/application.go` - RLock → Lock for cleanup writes
|
||||
- `docs/src/content/docs/reference/dialogs.mdx` - documented GTK4 limitations
|
||||
|
||||
### 2026-01-04 (Session 10)
|
||||
- Fixed Window → Zoom menu behavior to toggle maximize/restore (was incorrectly calling webview zoomIn)
|
||||
- Fixed radio button styling in GTK4 GMenu (now shows dots instead of checkmarks)
|
||||
- Implemented proper GMenu radio groups with string-valued stateful actions
|
||||
- All items in group share same action name with unique target values
|
||||
- Added `create_radio_menu_item()` C helper and `menuRadioItemNewWithGroup()` Go wrapper
|
||||
- Researched Wayland minimize behavior:
|
||||
- `gtk_window_minimize()` works on GNOME/KDE (sends xdg_toplevel_set_minimized)
|
||||
- May be no-op on tiling WMs (Sway, etc.) per Wayland protocol design
|
||||
- Fixed app not terminating when last window closed
|
||||
- Added quit logic to `unregisterWindow()` in `application_linux_gtk4.go`
|
||||
- Respects `DisableQuitOnLastWindowClosed` option
|
||||
- Fixed menu separators not showing
|
||||
- GMenu uses sections for visual separators (not separate separator items)
|
||||
- Rewrote menu processing to group items into sections, separators create new sections
|
||||
- Added `menuNewSection()`, `menuAppendSection()`, `menuAppendItemToSection()` helpers
|
||||
- Added CSS provider to reduce popover menu padding
|
||||
- Removed all debug println statements
|
||||
- Files modified:
|
||||
- `v3/pkg/application/linux_cgo_gtk4.go` - added radio group support, section helpers
|
||||
- `v3/pkg/application/linux_cgo_gtk4.c` - added create_radio_menu_item(), init_menu_css()
|
||||
- `v3/pkg/application/linux_cgo_gtk4.h` - added function declaration
|
||||
- `v3/pkg/application/application_linux_gtk4.go` - added quit-on-last-window logic
|
||||
- `v3/pkg/application/menu_linux_gtk4.go` - section-based menu processing, radio groups
|
||||
- `v3/pkg/application/menuitem_linux_gtk4.go` - updated radio item creation
|
||||
- `v3/pkg/application/webview_window_linux.go` - fixed zoom() to toggle maximize
|
||||
- `v3/pkg/application/window_manager.go` - removed debug output
|
||||
|
||||
### 2026-01-04 (Session 9)
|
||||
- Fixed GTK4 window creation crash (SIGSEGV in gtk_application_window_new)
|
||||
- **Root Cause**: GTK4 requires app to be "activated" before creating windows
|
||||
- **Solution**: Added activation synchronization mechanism:
|
||||
- Added `activated` channel and `sync.Once` to `linuxApp` struct
|
||||
- Added `markActivated()` method called from `activateLinux()` callback
|
||||
- Added `waitForActivation()` method for callers to block until ready
|
||||
- Modified `WebviewWindow.Run()` to wait for activation before `InvokeSync`
|
||||
- Files modified:
|
||||
- `v3/pkg/application/application_linux_gtk4.go` - activation gate
|
||||
- `v3/pkg/application/linux_cgo_gtk4.go` - call markActivated() in activateLinux
|
||||
- `v3/pkg/application/webview_window.go` - wait for activation on GTK4
|
||||
- GTK4 apps now create windows successfully without crashes
|
||||
|
||||
### 2026-01-04 (Session 8)
|
||||
- Fixed GTK3/GTK4 symbol conflict in operatingsystem package
|
||||
- Added `gtk3` build tag to `v3/internal/operatingsystem/webkit_linux.go`
|
||||
- Created `v3/internal/operatingsystem/webkit_linux_gtk4.go` with GTK4/WebKitGTK 6.0
|
||||
- Moved app initialization from `init()` to `newPlatformApp()` for cleaner setup
|
||||
- Resolved runtime crash: "GTK 2/3 symbols detected in GTK 4 process"
|
||||
- Verified menu example runs successfully with GTK 4.20.3 and WebKitGTK 2.50.3
|
||||
|
||||
### 2026-01-04 (Session 7)
|
||||
- Completed Phase 9: Keyboard Accelerators
|
||||
- Added namedKeysToGTK map with GDK keysym values for all special keys
|
||||
- Added parseKeyGTK() and parseModifiersGTK() conversion functions
|
||||
- Added acceleratorToGTK() to convert Wails accelerator format to GTK
|
||||
- Added setMenuItemAccelerator() Go wrapper that calls C helpers
|
||||
- Integrated accelerator setting in all menu item creation functions
|
||||
- Uses gtk_application_set_accels_for_action() for GTK4 shortcut binding
|
||||
|
||||
### 2026-01-04 (Session 6)
|
||||
- Completed Phase 8: Dialog System
|
||||
- Implemented GtkFileDialog for file open/save/folder dialogs
|
||||
- Implemented GtkAlertDialog for message dialogs
|
||||
- Added async callback system for GTK4 dialogs (no more gtk_dialog_run)
|
||||
- Added C helper functions and Go wrapper functions
|
||||
|
||||
### 2026-01-04 (Session 5 continued)
|
||||
- Completed Phase 6: Docker & Build System
|
||||
- Updated Dockerfile.linux-x86_64 and Dockerfile.linux-arm64 for GTK4 + GTK3
|
||||
- Added BUILD_TAGS environment variable support in build scripts
|
||||
- Added Taskfile targets for GTK4 (default) and GTK3 (legacy) builds
|
||||
|
||||
### 2026-01-04 (Session 5)
|
||||
- Completed Phase 5: Asset Server
|
||||
- Verified WebKitGTK 6.0 uses same URI scheme handler API as WebKitGTK 4.1
|
||||
- Added missing `onProcessRequest` export to linux_cgo_gtk4.go
|
||||
- Added missing `sendMessageToBackend` export to linux_cgo_gtk4.go
|
||||
- Confirmed asset server files (webkit6.go, request/responsewriter) are complete
|
||||
|
||||
### 2026-01-04 (Session 4)
|
||||
- Completed Phase 4: Menu System
|
||||
- Implemented GMenu/GAction architecture for GTK4 menus
|
||||
- Created GtkPopoverMenuBar integration
|
||||
- Added menu_linux_gtk4.go and menuitem_linux_gtk4.go
|
||||
- Added gtk3 build tags to original menu files
|
||||
- Implemented stateful actions for checkboxes and radio items
|
||||
|
||||
### 2026-01-04 (Session 3)
|
||||
- Completed Phase 3: Window Management
|
||||
- Implemented GTK4 event controllers (GtkEventControllerFocus, GtkGestureClick, GtkEventControllerKey)
|
||||
- Implemented window drag using GdkToplevel API (gdk_toplevel_begin_move/resize)
|
||||
- Implemented complete drag-and-drop with GtkDropTarget
|
||||
- Fixed window state detection (isMinimised, isMaximised, isFullscreen)
|
||||
- Fixed size() function to properly return window dimensions
|
||||
- Updated windowSetGeometryHints for GTK4 (uses gtk_widget_set_size_request)
|
||||
|
||||
### 2026-01-04 (Session 2)
|
||||
- Completed Phase 2: Doctor & Capabilities
|
||||
- Updated all 7 package managers for GTK4/WebKitGTK 6.0 as primary
|
||||
- Added GTKVersion and WebKitVersion fields to Capabilities struct
|
||||
- Created capabilities_linux_gtk3.go for legacy build path
|
||||
|
||||
### 2026-01-04 (Session 1)
|
||||
- Initial implementation of GTK4 build infrastructure
|
||||
- Added `gtk3` constraint to 5 existing files
|
||||
- Created 5 new GTK4 stub files
|
||||
- Updated UNRELEASED_CHANGELOG.md
|
||||
|
|
@ -1,419 +0,0 @@
|
|||
# Wails v3 iOS Architecture
|
||||
|
||||
## Executive Summary
|
||||
|
||||
This document provides a comprehensive technical architecture for iOS support in Wails v3. The implementation enables Go applications to run natively on iOS with a WKWebView frontend, maintaining the Wails philosophy of using web technologies for UI while leveraging Go for business logic.
|
||||
|
||||
## Table of Contents
|
||||
|
||||
1. [Architecture Overview](#architecture-overview)
|
||||
2. [Core Components](#core-components)
|
||||
3. [Layer Architecture](#layer-architecture)
|
||||
4. [Implementation Details](#implementation-details)
|
||||
5. [Battery Optimization](#battery-optimization)
|
||||
6. [Build System](#build-system)
|
||||
7. [Security Considerations](#security-considerations)
|
||||
8. [API Reference](#api-reference)
|
||||
|
||||
## Architecture Overview
|
||||
|
||||
### Design Principles
|
||||
|
||||
1. **Battery Efficiency First**: All architectural decisions prioritize battery life
|
||||
2. **No Network Ports**: Asset serving happens in-process via native APIs
|
||||
3. **Minimal WebView Instances**: Maximum 2 concurrent WebViews (1 primary, 1 for transitions)
|
||||
4. **Native Integration**: Deep iOS integration using Objective-C runtime
|
||||
5. **Wails v3 Compatibility**: Maintain API compatibility with existing Wails v3 applications
|
||||
|
||||
### High-Level Architecture
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────┐
|
||||
│ iOS Application │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ UIKit Framework │
|
||||
│ ┌─────────────────────────────────────────────────────┐ │
|
||||
│ │ WailsViewController │ │
|
||||
│ │ ┌───────────────────────────────────────────────┐ │ │
|
||||
│ │ │ WKWebView Instance │ │ │
|
||||
│ │ │ ┌─────────────────────────────────────────┐ │ │ │
|
||||
│ │ │ │ Web Application (HTML/JS) │ │ │ │
|
||||
│ │ │ └─────────────────────────────────────────┘ │ │ │
|
||||
│ │ └───────────────────────────────────────────────┘ │ │
|
||||
│ └─────────────────────────────────────────────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Bridge Layer (CGO) │
|
||||
│ ┌──────────────┐ ┌──────────────┐ ┌──────────────┐ │
|
||||
│ │URL Handler │ │JS Bridge │ │Message Handler│ │
|
||||
│ └──────────────┘ └──────────────┘ └──────────────┘ │
|
||||
├─────────────────────────────────────────────────────────────┤
|
||||
│ Go Runtime │
|
||||
│ ┌──────────────────────────────────────────────────────┐ │
|
||||
│ │ Wails Application │ │
|
||||
│ │ ┌──────────┐ ┌──────────┐ ┌──────────────────┐ │ │
|
||||
│ │ │App Logic │ │Services │ │Asset Server │ │ │
|
||||
│ │ └──────────┘ └──────────┘ └──────────────────┘ │ │
|
||||
│ └──────────────────────────────────────────────────────┘ │
|
||||
└─────────────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
## Core Components
|
||||
|
||||
### 1. Platform Layer (`application_ios.go`)
|
||||
|
||||
**Purpose**: Go interface for iOS platform operations
|
||||
|
||||
**Key Functions**:
|
||||
- `platformRun()`: Initialize and run the iOS application
|
||||
- `platformQuit()`: Gracefully shutdown the application
|
||||
- `isDarkMode()`: Detect iOS dark mode state
|
||||
- `ExecuteJavaScript(windowID uint, js string)`: Execute JS in WebView
|
||||
|
||||
**Exported Go Functions (Called from Objective-C)**:
|
||||
- `ServeAssetRequest(windowID C.uint, urlStr *C.char, callbackID C.uint)`
|
||||
- `HandleJSMessage(windowID C.uint, message *C.char)`
|
||||
|
||||
### 2. Native iOS Layer (`application_ios.m`)
|
||||
|
||||
**Components**:
|
||||
|
||||
#### WailsSchemeHandler
|
||||
```objc
|
||||
@interface WailsSchemeHandler : NSObject <WKURLSchemeHandler>
|
||||
```
|
||||
- Implements `WKURLSchemeHandler` protocol
|
||||
- Intercepts `wails://` URL requests
|
||||
- Bridges to Go for asset serving
|
||||
- Manages pending requests with callback IDs
|
||||
|
||||
**Methods**:
|
||||
- `startURLSchemeTask:`: Intercept request, call Go handler
|
||||
- `stopURLSchemeTask:`: Cancel pending request
|
||||
- `completeRequest:withData:mimeType:`: Complete request with data from Go
|
||||
|
||||
#### WailsMessageHandler
|
||||
```objc
|
||||
@interface WailsMessageHandler : NSObject <WKScriptMessageHandler>
|
||||
```
|
||||
- Implements JavaScript to Go communication
|
||||
- Handles `window.webkit.messageHandlers.external.postMessage()`
|
||||
- Serializes messages to JSON for Go processing
|
||||
|
||||
**Methods**:
|
||||
- `userContentController:didReceiveScriptMessage:`: Process JS messages
|
||||
|
||||
#### WailsViewController
|
||||
```objc
|
||||
@interface WailsViewController : UIViewController
|
||||
```
|
||||
- Main view controller containing WKWebView
|
||||
- Manages WebView lifecycle
|
||||
- Handles JavaScript execution requests
|
||||
|
||||
**Properties**:
|
||||
- `webView`: WKWebView instance
|
||||
- `schemeHandler`: Custom URL scheme handler
|
||||
- `messageHandler`: JS message handler
|
||||
- `windowID`: Unique window identifier
|
||||
|
||||
**Methods**:
|
||||
- `viewDidLoad`: Initialize WebView with configuration
|
||||
- `executeJavaScript:`: Run JS code in WebView
|
||||
|
||||
### 3. Bridge Layer (CGO)
|
||||
|
||||
**C Interface Functions**:
|
||||
```c
|
||||
void ios_app_init(void); // Initialize iOS app
|
||||
void ios_app_run(void); // Run main loop
|
||||
void ios_app_quit(void); // Quit application
|
||||
bool ios_is_dark_mode(void); // Check dark mode
|
||||
unsigned int ios_create_webview(void); // Create WebView
|
||||
void ios_execute_javascript(unsigned int windowID, const char* js);
|
||||
void ios_complete_request(unsigned int callbackID, const char* data, const char* mimeType);
|
||||
```
|
||||
|
||||
## Layer Architecture
|
||||
|
||||
### Layer 1: Presentation Layer (WebView)
|
||||
|
||||
**Responsibilities**:
|
||||
- Render HTML/CSS/JavaScript UI
|
||||
- Handle user interactions
|
||||
- Communicate with native layer
|
||||
|
||||
**Key Features**:
|
||||
- WKWebView for modern web standards
|
||||
- Hardware-accelerated rendering
|
||||
- Efficient memory management
|
||||
|
||||
### Layer 2: Communication Layer
|
||||
|
||||
**Request Interception**:
|
||||
```
|
||||
WebView Request → WKURLSchemeHandler → Go ServeAssetRequest → AssetServer → Response
|
||||
```
|
||||
|
||||
**JavaScript Bridge**:
|
||||
```
|
||||
JS postMessage → WKScriptMessageHandler → Go HandleJSMessage → Process → ExecuteJavaScript
|
||||
```
|
||||
|
||||
### Layer 3: Application Layer (Go)
|
||||
|
||||
**Components**:
|
||||
- Application lifecycle management
|
||||
- Service binding and method calls
|
||||
- Asset serving from embedded fs.FS
|
||||
- Business logic execution
|
||||
|
||||
### Layer 4: Platform Integration Layer
|
||||
|
||||
**iOS-Specific Features**:
|
||||
- Dark mode detection
|
||||
- System appearance integration
|
||||
- iOS-specific optimizations
|
||||
|
||||
## Implementation Details
|
||||
|
||||
### Request Handling Flow
|
||||
|
||||
1. **WebView makes request** to `wails://localhost/path`
|
||||
2. **WKURLSchemeHandler intercepts** request
|
||||
3. **Creates callback ID** and stores `WKURLSchemeTask`
|
||||
4. **Calls Go function** `ServeAssetRequest` with URL and callback ID
|
||||
5. **Go processes request** through AssetServer
|
||||
6. **Go calls** `ios_complete_request` with response data
|
||||
7. **Objective-C completes** the `WKURLSchemeTask` with response
|
||||
|
||||
### JavaScript Execution Flow
|
||||
|
||||
1. **Go calls** `ios_execute_javascript` with JS code
|
||||
2. **Bridge dispatches** to main thread
|
||||
3. **WKWebView evaluates** JavaScript
|
||||
4. **Completion handler** logs any errors
|
||||
|
||||
### Message Passing Flow
|
||||
|
||||
1. **JavaScript calls** `window.webkit.messageHandlers.wails.postMessage(data)`
|
||||
2. **WKScriptMessageHandler receives** message
|
||||
3. **Serializes to JSON** and passes to Go
|
||||
4. **Go processes** message in `HandleJSMessage`
|
||||
5. **Go can respond** via `ExecuteJavaScript`
|
||||
|
||||
## Battery Optimization
|
||||
|
||||
### WebView Configuration
|
||||
|
||||
```objc
|
||||
// Disable unnecessary features
|
||||
config.suppressesIncrementalRendering = NO;
|
||||
config.allowsInlineMediaPlayback = YES;
|
||||
config.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypeNone;
|
||||
```
|
||||
|
||||
### Memory Management
|
||||
|
||||
1. **Single WebView Instance**: Reuse instead of creating new instances
|
||||
2. **Automatic Reference Counting**: Use ARC for Objective-C objects
|
||||
3. **Lazy Loading**: Initialize components only when needed
|
||||
4. **Resource Cleanup**: Properly release resources when done
|
||||
|
||||
### Request Optimization
|
||||
|
||||
1. **In-Process Serving**: No network overhead
|
||||
2. **Direct Memory Transfer**: Pass data directly without serialization
|
||||
3. **Efficient Caching**: Leverage WKWebView's built-in cache
|
||||
4. **Minimal Wake Locks**: No background network activity
|
||||
|
||||
## Build System
|
||||
|
||||
### Build Tags
|
||||
|
||||
```go
|
||||
//go:build ios
|
||||
```
|
||||
|
||||
### CGO Configuration
|
||||
|
||||
```go
|
||||
#cgo CFLAGS: -x objective-c -fobjc-arc
|
||||
#cgo LDFLAGS: -framework Foundation -framework UIKit -framework WebKit
|
||||
```
|
||||
|
||||
### Build Script (`build_ios.sh`)
|
||||
|
||||
**Steps**:
|
||||
1. Check dependencies (go, xcodebuild, xcrun)
|
||||
2. Set up iOS cross-compilation environment
|
||||
3. Build Go binary with iOS tags
|
||||
4. Create app bundle structure
|
||||
5. Generate Info.plist
|
||||
6. Sign for simulator
|
||||
7. Create launch script
|
||||
|
||||
**Environment Variables**:
|
||||
```bash
|
||||
export CGO_ENABLED=1
|
||||
export GOOS=ios
|
||||
export GOARCH=arm64
|
||||
export SDK_PATH=$(xcrun --sdk iphonesimulator --show-sdk-path)
|
||||
```
|
||||
|
||||
### Simulator Deployment
|
||||
|
||||
```bash
|
||||
xcrun simctl install "$DEVICE_ID" "WailsIOSDemo.app"
|
||||
xcrun simctl launch "$DEVICE_ID" "com.wails.iosdemo"
|
||||
```
|
||||
|
||||
## Security Considerations
|
||||
|
||||
### URL Scheme Security
|
||||
|
||||
1. **Custom Scheme**: Use `wails://` to avoid conflicts
|
||||
2. **Origin Validation**: Only serve to authorized WebViews
|
||||
3. **No External Access**: Scheme handler only responds to app's WebView
|
||||
|
||||
### JavaScript Execution
|
||||
|
||||
1. **Input Validation**: Sanitize JS code before execution
|
||||
2. **Sandboxed Execution**: WKWebView provides isolation
|
||||
3. **No eval()**: Avoid dynamic code evaluation
|
||||
|
||||
### Data Protection
|
||||
|
||||
1. **In-Memory Only**: No temporary files on disk
|
||||
2. **ATS Compliance**: App Transport Security enabled
|
||||
3. **Secure Communication**: All data stays within app process
|
||||
|
||||
## API Reference
|
||||
|
||||
### Go API
|
||||
|
||||
#### Application Functions
|
||||
|
||||
```go
|
||||
// Create new iOS application
|
||||
app := application.New(application.Options{
|
||||
Name: "App Name",
|
||||
Description: "App Description",
|
||||
})
|
||||
|
||||
// Run the application
|
||||
app.Run()
|
||||
|
||||
// Execute JavaScript
|
||||
app.ExecuteJavaScript(windowID, "console.log('Hello')")
|
||||
```
|
||||
|
||||
#### Service Binding
|
||||
|
||||
```go
|
||||
type MyService struct{}
|
||||
|
||||
func (s *MyService) Greet(name string) string {
|
||||
return fmt.Sprintf("Hello, %s!", name)
|
||||
}
|
||||
|
||||
app := application.New(application.Options{
|
||||
Services: []application.Service{
|
||||
application.NewService(&MyService{}),
|
||||
},
|
||||
})
|
||||
```
|
||||
|
||||
### JavaScript API
|
||||
|
||||
#### Send Message to Go
|
||||
|
||||
```javascript
|
||||
window.webkit.messageHandlers.wails.postMessage({
|
||||
type: 'methodCall',
|
||||
service: 'MyService',
|
||||
method: 'Greet',
|
||||
args: ['World']
|
||||
});
|
||||
```
|
||||
|
||||
#### Receive from Go
|
||||
|
||||
```javascript
|
||||
window.wailsCallback = function(data) {
|
||||
console.log('Received:', data);
|
||||
};
|
||||
```
|
||||
|
||||
### Objective-C Bridge API
|
||||
|
||||
#### From Go to Objective-C
|
||||
|
||||
```c
|
||||
// Execute JavaScript
|
||||
ios_execute_javascript(windowID, "alert('Hello')");
|
||||
|
||||
// Complete asset request
|
||||
ios_complete_request(callbackID, htmlData, "text/html");
|
||||
```
|
||||
|
||||
#### From Objective-C to Go
|
||||
|
||||
```c
|
||||
// Serve asset request
|
||||
ServeAssetRequest(windowID, urlString, callbackID);
|
||||
|
||||
// Handle JavaScript message
|
||||
HandleJSMessage(windowID, jsonMessage);
|
||||
```
|
||||
|
||||
## Performance Metrics
|
||||
|
||||
### Target Metrics
|
||||
|
||||
- **WebView Creation**: < 100ms
|
||||
- **Asset Request**: < 10ms for cached, < 50ms for first load
|
||||
- **JS Execution**: < 5ms for simple scripts
|
||||
- **Message Passing**: < 2ms round trip
|
||||
- **Memory Usage**: < 50MB baseline
|
||||
- **Battery Impact**: < 2% per hour active use
|
||||
|
||||
### Monitoring
|
||||
|
||||
1. **Xcode Instruments**: CPU, Memory, Energy profiling
|
||||
2. **WebView Inspector**: JavaScript performance
|
||||
3. **Go Profiling**: pprof for Go code analysis
|
||||
|
||||
## Future Enhancements
|
||||
|
||||
### Phase 1: Core Stability
|
||||
- [ ] Production-ready error handling
|
||||
- [ ] Comprehensive test suite
|
||||
- [ ] Performance optimization
|
||||
|
||||
### Phase 2: Feature Parity
|
||||
- [ ] Multiple window support
|
||||
- [ ] System tray integration
|
||||
- [ ] Native menu implementation
|
||||
|
||||
### Phase 3: iOS-Specific Features
|
||||
- [ ] Widget extension support
|
||||
- [ ] App Clip support
|
||||
- [ ] ShareSheet integration
|
||||
- [ ] Siri Shortcuts
|
||||
|
||||
### Phase 4: Advanced Features
|
||||
- [ ] Background task support
|
||||
- [ ] Push notifications
|
||||
- [ ] CloudKit integration
|
||||
- [ ] Apple Watch companion app
|
||||
|
||||
## Conclusion
|
||||
|
||||
This architecture provides a solid foundation for iOS support in Wails v3. The design prioritizes battery efficiency, native performance, and seamless integration with the existing Wails ecosystem. The proof of concept demonstrates all four required capabilities:
|
||||
|
||||
1. ✅ **WebView Creation**: Native WKWebView with optimized configuration
|
||||
2. ✅ **Request Interception**: Custom scheme handler without network ports
|
||||
3. ✅ **JavaScript Execution**: Bidirectional communication bridge
|
||||
4. ✅ **iOS Simulator Support**: Complete build and deployment pipeline
|
||||
|
||||
The architecture is designed to scale from this proof of concept to a full production implementation while maintaining the simplicity and elegance that Wails developers expect.
|
||||
|
|
@ -25,7 +25,7 @@ Erschaffe Desktop Anwendungen mit Go & Web Technologien.
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
@ -98,9 +98,9 @@ The installation instructions are on the [official website](https://wails.io/doc
|
|||
This project is supported by these kind people / companies:
|
||||
<img src="website/static/img/sponsors.svg" style="width:100%;max-width:800px;"/>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://wails.io/img/sponsor/jetbrains-grayscale.webp" style="width: 100px"/>
|
||||
</p>
|
||||
## Powered By
|
||||
|
||||
[](https://jb.gg/OpenSource)
|
||||
|
||||
## FAQ
|
||||
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -25,7 +25,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -27,7 +27,7 @@
|
|||
<img src="https://cdn.rawgit.com/sindresorhus/awesome/d7305f38d29fed78fa85652e3a63e154dd8e8829/media/badge.svg" alt="Awesome" />
|
||||
</a>
|
||||
<a href="https://discord.gg/BrRSWTaxVK">
|
||||
<img alt="Discord" src="https://dcbadge.vercel.app/api/server/BrRSWTaxVK?style=flat"/>
|
||||
<img alt="Discord" src="https://img.shields.io/discord/1042734330029547630?logo=discord"/>
|
||||
</a>
|
||||
<br/>
|
||||
<a href="https://github.com/wailsapp/wails/actions/workflows/build-and-test.yml" rel="nofollow">
|
||||
|
|
|
|||
|
|
@ -16,11 +16,6 @@ includes:
|
|||
dir: v3
|
||||
optional: true
|
||||
|
||||
docs:
|
||||
taskfile: docs
|
||||
dir: docs
|
||||
optional: true
|
||||
|
||||
tasks:
|
||||
contributors:check:
|
||||
cmds:
|
||||
|
|
|
|||
21
docs/.gitignore
vendored
|
|
@ -1,21 +0,0 @@
|
|||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# dependencies
|
||||
node_modules/
|
||||
|
||||
# logs
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
pnpm-debug.log*
|
||||
|
||||
|
||||
# environment variables
|
||||
.env
|
||||
.env.production
|
||||
|
||||
# macOS-specific files
|
||||
.DS_Store
|
||||
|
|
@ -1 +0,0 @@
|
|||
save-exact=true
|
||||
4
docs/.vscode/extensions.json
vendored
|
|
@ -1,4 +0,0 @@
|
|||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
||||
11
docs/.vscode/launch.json
vendored
|
|
@ -1,11 +0,0 @@
|
|||
{
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"command": "./node_modules/.bin/astro dev",
|
||||
"name": "Development server",
|
||||
"request": "launch",
|
||||
"type": "node-terminal"
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
@ -1 +0,0 @@
|
|||
v3alpha.wails.io
|
||||
|
|
@ -1,65 +0,0 @@
|
|||
# Wails v3 Documentation
|
||||
|
||||
[](https://starlight.astro.build)
|
||||
|
||||
World-class documentation for Wails v3, redesigned following Netflix documentation principles.
|
||||
|
||||
## 📚 Documentation Redesign (2025-10-01)
|
||||
|
||||
This documentation has been completely redesigned to follow the **Netflix approach** to developer documentation:
|
||||
|
||||
- **Problem-first framing** - Start with why, not what
|
||||
- **Progressive disclosure** - Multiple entry points for different skill levels
|
||||
- **Real production examples** - No toy code
|
||||
- **Story-Code-Context pattern** - Why → How → When
|
||||
- **Scannable content** - Clear structure, visual aids
|
||||
|
||||
**Status:** Foundation complete (~20%), ready for content migration
|
||||
|
||||
See [IMPLEMENTATION_SUMMARY.md](./IMPLEMENTATION_SUMMARY.md) for full details.
|
||||
|
||||
## 🚀 Project Structure
|
||||
|
||||
Inside of your Astro + Starlight project, you'll see the following folders and
|
||||
files:
|
||||
|
||||
```sh
|
||||
.
|
||||
├── public/
|
||||
├── src/
|
||||
│ ├── assets/
|
||||
│ ├── content/
|
||||
│ │ ├── docs/
|
||||
│ │ └── config.ts
|
||||
│ └── env.d.ts
|
||||
├── astro.config.mjs
|
||||
├── package.json
|
||||
└── tsconfig.json
|
||||
```
|
||||
|
||||
Starlight looks for `.md` or `.mdx` files in the `src/content/docs/` directory.
|
||||
Each file is exposed as a route based on its file name.
|
||||
|
||||
Images can be added to `src/assets/` and embedded in Markdown with a relative
|
||||
link.
|
||||
|
||||
Static assets, like favicons, can be placed in the `public/` directory.
|
||||
|
||||
## 🧞 Commands
|
||||
|
||||
All commands are run from the root of the project, from a terminal:
|
||||
|
||||
| Command | Action |
|
||||
| :------------------------ | :----------------------------------------------- |
|
||||
| `npm install` | Installs dependencies |
|
||||
| `npm run dev` | Starts local dev server at `localhost:4321` |
|
||||
| `npm run build` | Build your production site to `./dist/` |
|
||||
| `npm run preview` | Preview your build locally, before deploying |
|
||||
| `npm run astro ...` | Run CLI commands like `astro add`, `astro check` |
|
||||
| `npm run astro -- --help` | Get help using the Astro CLI |
|
||||
|
||||
## 👀 Want to learn more?
|
||||
|
||||
Check out [Starlight’s docs](https://starlight.astro.build/), read
|
||||
[the Astro documentation](https://docs.astro.build), or jump into the
|
||||
[Astro Discord server](https://astro.build/chat).
|
||||
|
|
@ -1,36 +0,0 @@
|
|||
# https://taskfile.dev
|
||||
|
||||
version: '3'
|
||||
|
||||
vars:
|
||||
# Change this to switch package managers: bun, npm, pnpm, yarn
|
||||
PKG_MANAGER: npm
|
||||
|
||||
tasks:
|
||||
|
||||
setup:
|
||||
summary: Setup the project (including D2 diagram tool)
|
||||
preconditions:
|
||||
- sh: '{{.PKG_MANAGER}} --version'
|
||||
msg: "Looks like {{.PKG_MANAGER}} isn't installed."
|
||||
- sh: 'go version'
|
||||
msg: "Go is not installed. Install from https://go.dev/dl/"
|
||||
cmds:
|
||||
- '{{.PKG_MANAGER}} install'
|
||||
- go install oss.terrastruct.com/d2@latest
|
||||
- echo "✓ Setup complete. D2 installed to $(go env GOPATH)/bin/d2"
|
||||
|
||||
dev:
|
||||
summary: Run the dev server
|
||||
deps: [setup]
|
||||
cmds:
|
||||
- '{{.PKG_MANAGER}} run dev'
|
||||
|
||||
build:
|
||||
summary: Build the docs
|
||||
preconditions:
|
||||
- sh: '{{.PKG_MANAGER}} --version'
|
||||
msg: "Looks like {{.PKG_MANAGER}} isn't installed."
|
||||
cmds:
|
||||
- '{{.PKG_MANAGER}} run build'
|
||||
|
||||
|
|
@ -1,351 +0,0 @@
|
|||
// @ts-check
|
||||
import { defineConfig } from "astro/config";
|
||||
import starlight from "@astrojs/starlight";
|
||||
import sitemap from "@astrojs/sitemap";
|
||||
import starlightLinksValidator from "starlight-links-validator";
|
||||
import starlightImageZoom from "starlight-image-zoom";
|
||||
import starlightBlog from "starlight-blog";
|
||||
import { authors } from "./src/content/authors";
|
||||
import d2 from 'astro-d2';
|
||||
import react from '@astrojs/react';
|
||||
|
||||
// https://astro.build/config
|
||||
export default defineConfig({
|
||||
site: "https://wails.io",
|
||||
trailingSlash: "ignore",
|
||||
compressHTML: true,
|
||||
output: "static",
|
||||
build: { format: "directory" },
|
||||
devToolbar: { enabled: true },
|
||||
integrations: [
|
||||
react(),
|
||||
d2(),
|
||||
sitemap(),
|
||||
starlight({
|
||||
title: "",
|
||||
titleDelimiter: "",
|
||||
logo: {
|
||||
dark: "./src/assets/wails-logo-horizontal-dark.svg",
|
||||
light: "./src/assets/wails-logo-horizontal-light.svg",
|
||||
},
|
||||
favicon: "./public/favicon.svg",
|
||||
description: "Build beautiful desktop applications using Go and modern web technologies.",
|
||||
pagefind: true,
|
||||
customCss: ["./src/stylesheets/extra.css"],
|
||||
lastUpdated: true,
|
||||
pagination: true,
|
||||
editLink: {
|
||||
baseUrl: "https://github.com/wailsapp/wails/edit/v3-alpha/docs",
|
||||
},
|
||||
social: [
|
||||
{ icon: 'github', label: 'GitHub', href: 'https://github.com/wailsapp/wails' },
|
||||
{ icon: 'discord', label: 'Discord', href: 'https://discord.gg/JDdSxwjhGf' },
|
||||
{ icon: 'x.com', label: 'X', href: 'https://x.com/wailsapp' },
|
||||
],
|
||||
head: [
|
||||
{
|
||||
tag: 'script',
|
||||
content: `
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const socialLinks = document.querySelector('.social-icons');
|
||||
if (socialLinks) {
|
||||
const sponsorLink = document.createElement('a');
|
||||
sponsorLink.href = 'https://github.com/sponsors/leaanthony';
|
||||
sponsorLink.className = 'sl-flex';
|
||||
sponsorLink.title = 'Sponsor';
|
||||
sponsorLink.innerHTML = '<span class="sr-only">Sponsor</span><svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" viewBox="0 0 24 24" fill="#ef4444" stroke="none"><path d="M19 14c1.49-1.46 3-3.21 3-5.5A5.5 5.5 0 0 0 16.5 3c-1.76 0-3 .5-4.5 2-1.5-1.5-2.74-2-4.5-2A5.5 5.5 0 0 0 2 8.5c0 2.3 1.5 4.05 3 5.5l7 7Z"/></svg>';
|
||||
socialLinks.appendChild(sponsorLink);
|
||||
}
|
||||
});
|
||||
`,
|
||||
},
|
||||
],
|
||||
defaultLocale: "root",
|
||||
locales: {
|
||||
root: { label: "English", lang: "en", dir: "ltr" },
|
||||
},
|
||||
plugins: [
|
||||
starlightImageZoom(),
|
||||
starlightBlog({
|
||||
title: "Wails Blog",
|
||||
authors: authors,
|
||||
}),
|
||||
],
|
||||
sidebar: [
|
||||
{ label: "Home", link: "/" },
|
||||
|
||||
// Progressive Onboarding - Netflix Principle: Start with the problem
|
||||
{ label: "Why Wails?", link: "/quick-start/why-wails" },
|
||||
|
||||
{
|
||||
label: "Quick Start",
|
||||
collapsed: false,
|
||||
items: [
|
||||
{ label: "Installation", link: "/quick-start/installation" },
|
||||
{ label: "Your First App", link: "/quick-start/first-app" },
|
||||
{ label: "Next Steps", link: "/quick-start/next-steps" },
|
||||
],
|
||||
},
|
||||
|
||||
// Tutorials
|
||||
{
|
||||
label: "Tutorials",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "tutorials" },
|
||||
},
|
||||
|
||||
// Core Concepts
|
||||
{
|
||||
label: "Core Concepts",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "How Wails Works", link: "/concepts/architecture" },
|
||||
{ label: "Manager API", link: "/concepts/manager-api" },
|
||||
{ label: "Application Lifecycle", link: "/concepts/lifecycle" },
|
||||
{ label: "Go-Frontend Bridge", link: "/concepts/bridge" },
|
||||
{ label: "Build System", link: "/concepts/build-system" },
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
label: "Features",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
label: "Windows",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Window Basics", link: "/features/windows/basics" },
|
||||
{ label: "Window Options", link: "/features/windows/options" },
|
||||
{ label: "Multiple Windows", link: "/features/windows/multiple" },
|
||||
{ label: "Frameless Windows", link: "/features/windows/frameless" },
|
||||
{ label: "Window Events", link: "/features/windows/events" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Menus",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Application Menus", link: "/features/menus/application" },
|
||||
{ label: "Context Menus", link: "/features/menus/context" },
|
||||
{ label: "System Tray Menus", link: "/features/menus/systray" },
|
||||
{ label: "Menu Reference", link: "/features/menus/reference" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Bindings & Services",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Method Binding", link: "/features/bindings/methods" },
|
||||
{ label: "Services", link: "/features/bindings/services" },
|
||||
{ label: "Data Models", link: "/features/bindings/models" },
|
||||
{ label: "Enums", link: "/features/bindings/enums" },
|
||||
{ label: "Advanced Binding", link: "/features/bindings/advanced" },
|
||||
{ label: "Best Practices", link: "/features/bindings/best-practices" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Events",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Event System", link: "/features/events/system" },
|
||||
{ label: "Application Events", link: "/features/events/application" },
|
||||
{ label: "Window Events", link: "/features/events/window" },
|
||||
{ label: "Custom Events", link: "/features/events/custom" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Dialogs",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "File Dialogs", link: "/features/dialogs/file" },
|
||||
{ label: "Message Dialogs", link: "/features/dialogs/message" },
|
||||
{ label: "Custom Dialogs", link: "/features/dialogs/custom" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Clipboard",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/clipboard" },
|
||||
},
|
||||
{
|
||||
label: "Browser",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/browser" },
|
||||
},
|
||||
{
|
||||
label: "Drag & Drop",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/drag-and-drop" },
|
||||
},
|
||||
{
|
||||
label: "Keyboard",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/keyboard" },
|
||||
},
|
||||
{
|
||||
label: "Notifications",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/notifications" },
|
||||
},
|
||||
{
|
||||
label: "Screens",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/screens" },
|
||||
},
|
||||
{
|
||||
label: "Environment",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/environment" },
|
||||
},
|
||||
{
|
||||
label: "Platform-Specific",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "features/platform" },
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Guides - Task-oriented patterns (Netflix: When to use it, when not to use it)
|
||||
{
|
||||
label: "Guides",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{
|
||||
label: "Development",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Project Structure", link: "/guides/dev/project-structure" },
|
||||
{ label: "Development Workflow", link: "/guides/dev/workflow" },
|
||||
{ label: "Debugging", link: "/guides/dev/debugging" },
|
||||
{ label: "Testing", link: "/guides/dev/testing" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Building & Packaging",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Building Applications", link: "/guides/build/building" },
|
||||
{ label: "Build Customization", link: "/guides/build/customization" },
|
||||
{ label: "Cross-Platform Builds", link: "/guides/build/cross-platform" },
|
||||
{ label: "Code Signing", link: "/guides/build/signing" },
|
||||
{ label: "Windows Packaging", link: "/guides/build/windows" },
|
||||
{ label: "macOS Packaging", link: "/guides/build/macos" },
|
||||
{ label: "Linux Packaging", link: "/guides/build/linux" },
|
||||
{ label: "MSIX Packaging", link: "/guides/build/msix" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Distribution",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Auto-Updates", link: "/guides/distribution/auto-updates" },
|
||||
{ label: "File Associations", link: "/guides/distribution/file-associations" },
|
||||
{ label: "Custom Protocols", link: "/guides/distribution/custom-protocols" },
|
||||
{ label: "Single Instance", link: "/guides/distribution/single-instance" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Integration Patterns",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Using Gin Router", link: "/guides/patterns/gin-routing" },
|
||||
{ label: "Gin Services", link: "/guides/patterns/gin-services" },
|
||||
{ label: "Database Integration", link: "/guides/patterns/database" },
|
||||
{ label: "REST APIs", link: "/guides/patterns/rest-api" },
|
||||
],
|
||||
},
|
||||
{
|
||||
label: "Advanced Topics",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Server Build", link: "/guides/server-build", badge: { text: "Experimental", variant: "caution" } },
|
||||
{ label: "Custom Templates", link: "/guides/advanced/custom-templates" },
|
||||
{ label: "WML (Wails Markup)", link: "/guides/advanced/wml" },
|
||||
{ label: "Panic Handling", link: "/guides/advanced/panic-handling" },
|
||||
{ label: "Security Best Practices", link: "/guides/advanced/security" },
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
// Reference - Comprehensive API docs (Netflix: Complete technical reference)
|
||||
{
|
||||
label: "API Reference",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Overview", link: "/reference/overview" },
|
||||
{ label: "Application", link: "/reference/application" },
|
||||
{ label: "Window", link: "/reference/window" },
|
||||
{ label: "Menu", link: "/reference/menu" },
|
||||
{ label: "Events", link: "/reference/events" },
|
||||
{ label: "Dialogs", link: "/reference/dialogs" },
|
||||
{ label: "Frontend Runtime", link: "/reference/frontend-runtime" },
|
||||
{ label: "CLI", link: "/reference/cli" },
|
||||
],
|
||||
},
|
||||
|
||||
// Contributing
|
||||
{
|
||||
label: "Contributing",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Getting Started", link: "/contributing/getting-started" },
|
||||
{ label: "Development Setup", link: "/contributing/setup" },
|
||||
{ label: "Coding Standards", link: "/contributing/standards" },
|
||||
],
|
||||
},
|
||||
|
||||
// Migration & Troubleshooting
|
||||
{
|
||||
label: "Migration",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "From v2 to v3", link: "/migration/v2-to-v3" },
|
||||
{ label: "From Electron", link: "/migration/from-electron" },
|
||||
],
|
||||
},
|
||||
|
||||
{
|
||||
label: "Troubleshooting",
|
||||
collapsed: true,
|
||||
autogenerate: { directory: "troubleshooting" },
|
||||
},
|
||||
|
||||
// Community & Resources
|
||||
{
|
||||
label: "Community",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Links", link: "/community/links" },
|
||||
{ label: "Templates", link: "/community/templates" },
|
||||
{
|
||||
label: "Showcase",
|
||||
collapsed: true,
|
||||
items: [
|
||||
{ label: "Overview", link: "/community/showcase" },
|
||||
{
|
||||
label: "Applications",
|
||||
autogenerate: {
|
||||
directory: "community/showcase",
|
||||
collapsed: true,
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
{ label: "What's New", link: "/whats-new" },
|
||||
{ label: "Status", link: "/status" },
|
||||
{ label: "Changelog", link: "/changelog" },
|
||||
{
|
||||
label: "Sponsor",
|
||||
link: "https://github.com/sponsors/leaanthony",
|
||||
badge: { text: "❤️" },
|
||||
},
|
||||
{ label: "Credits", link: "/credits" },
|
||||
],
|
||||
}),
|
||||
],
|
||||
});
|
||||
9082
docs/package-lock.json
generated
|
|
@ -1,31 +0,0 @@
|
|||
{
|
||||
"name": "wails-docs",
|
||||
"type": "module",
|
||||
"version": "0.0.1",
|
||||
"scripts": {
|
||||
"dev": "astro dev",
|
||||
"start": "astro dev",
|
||||
"build": "astro check && astro build",
|
||||
"preview": "astro preview",
|
||||
"astro": "astro"
|
||||
},
|
||||
"dependencies": {
|
||||
"@astrojs/check": "^0.9.4",
|
||||
"@astrojs/react": "^4.1.0",
|
||||
"@astrojs/starlight": "0.36.2",
|
||||
"@types/react": "^19.0.1",
|
||||
"@types/react-dom": "^19.0.2",
|
||||
"astro": "^5.0.0",
|
||||
"astro-d2": "^0.5.0",
|
||||
"framer-motion": "^11.14.4",
|
||||
"motion": "^11.14.4",
|
||||
"react": "^19.0.0",
|
||||
"react-dom": "^19.0.0",
|
||||
"sharp": "^0.33.5",
|
||||
"starlight-blog": "0.25.1",
|
||||
"starlight-image-zoom": "^0.9.0",
|
||||
"starlight-links-validator": "^0.13.4",
|
||||
"starlight-showcases": "^0.2.0",
|
||||
"typescript": "^5.7.2"
|
||||
}
|
||||
}
|
||||
|
Before Width: | Height: | Size: 38 KiB |
|
Before Width: | Height: | Size: 33 KiB |
|
|
@ -1 +0,0 @@
|
|||
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%" version="1.1" viewBox="0 0 550 310" xml:space="preserve" style="fill-rule:evenodd;clip-rule:evenodd;stroke-linejoin:round;stroke-miterlimit:2"><g><path d="M0.883,-0.081L0.121,0.081L0.256,-0.063L0.883,-0.081Z" transform="matrix(-166.599,4.57132,4.57132,166.599,147.403,167.648)" style="fill:url(#_Linear1);fill-rule:nonzero"/></g><g><path d="M0.878,-0.285L-0.073,0.71L-1.186,0.542L0.015,0.207L-0.846,0.077L0.355,-0.258L-0.505,-0.388L0.649,-0.71L0.878,-0.285Z" transform="matrix(-106.443,-16.0669,-16.0669,106.443,428.19,188.033)" style="fill:url(#_Linear2);fill-rule:nonzero"/></g><g><path d="M0.44,-0.04L0.265,-0.056L0.177,0.437L-0.311,-0.255L0.262,-0.437L0.568,-0.437L0.44,-0.04Z" transform="matrix(-114.484,-162.408,-162.408,114.484,333.291,285.804)" style="fill:url(#_Linear3);fill-rule:nonzero"/></g><g><path d="M0.622,-0.115L0.761,-0.115L0.806,-0.013L0.826,0.182L0.622,-0.115Z" transform="matrix(238.126,298.893,298.893,-238.126,113.516,-150.536)" style="fill:url(#_Linear4);fill-rule:nonzero"/></g><g><path d="M0.467,0.005L0.49,0.062L0.271,-0.062L0.467,0.005Z" transform="matrix(-369.529,-97.4118,-97.4118,369.529,582.38,94.027)" style="fill:url(#_Linear5);fill-rule:nonzero"/></g><g><path d="M0.2,0.001L0.219,-0.018L0.614,0.012L0.519,0.089L0.282,0.068L0.2,0.135L0.463,0.194L0.374,0.266L0.138,0.186L0.047,0.033L-0.131,-0.266L0.2,0.001Z" transform="matrix(-496.156,-53.9751,-53.9751,496.156,367.888,125.085)" style="fill:url(#_Linear6);fill-rule:nonzero"/></g><g><path d="M269.095,104.527L287.764,111.419L263.632,106.75L269.095,104.527Z" transform="matrix(0.436503,-1.22916,4.88651,1.73532,-368.043,253.619)" style="fill:#fff"/></g><defs><linearGradient id="_Linear1" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(1,-3.46945e-18,3.46945e-18,1,0,-3.05761e-06)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#e33232;stop-opacity:1"/><stop offset="1" style="stop-color:#6b000d;stop-opacity:1"/></linearGradient><linearGradient id="_Linear2" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(1,0,0,1,0,-2.75467e-06)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#e33232;stop-opacity:1"/><stop offset="1" style="stop-color:#6b000d;stop-opacity:1"/></linearGradient><linearGradient id="_Linear3" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(1,-1.11022e-16,1.11022e-16,1,0,-2.61861e-06)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#e33232;stop-opacity:1"/><stop offset="1" style="stop-color:#6b000d;stop-opacity:1"/></linearGradient><linearGradient id="_Linear4" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(-0.801899,-0.59746,0.59746,-0.801899,1.3495,0.447457)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#e33232;stop-opacity:1"/><stop offset="1" style="stop-color:#6b000d;stop-opacity:1"/></linearGradient><linearGradient id="_Linear5" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(1,-2.77556e-17,2.77556e-17,1,0,-1.92826e-06)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#e33232;stop-opacity:1"/><stop offset="1" style="stop-color:#6b000d;stop-opacity:1"/></linearGradient><linearGradient id="_Linear6" x1="0" x2="1" y1="0" y2="0" gradientTransform="matrix(1,0,0,1,0,9.68429e-07)" gradientUnits="userSpaceOnUse"><stop offset="0" style="stop-color:#e33232;stop-opacity:1"/><stop offset="1" style="stop-color:#6b000d;stop-opacity:1"/></linearGradient></defs></svg>
|
||||
|
Before Width: | Height: | Size: 3.4 KiB |
|
Before Width: | Height: | Size: 498 KiB |
|
Before Width: | Height: | Size: 8 KiB |
|
Before Width: | Height: | Size: 27 KiB |
|
Before Width: | Height: | Size: 190 KiB |
|
Before Width: | Height: | Size: 42 KiB |
|
Before Width: | Height: | Size: 23 KiB |
|
Before Width: | Height: | Size: 35 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 503 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 61 KiB |
|
Before Width: | Height: | Size: 41 KiB |
|
Before Width: | Height: | Size: 20 KiB |
|
Before Width: | Height: | Size: 25 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 58 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 67 KiB |
|
Before Width: | Height: | Size: 68 KiB |
|
Before Width: | Height: | Size: 62 KiB |
|
Before Width: | Height: | Size: 17 KiB |
|
Before Width: | Height: | Size: 110 KiB |
|
Before Width: | Height: | Size: 19 KiB |
|
Before Width: | Height: | Size: 50 KiB |
|
Before Width: | Height: | Size: 65 KiB |
|
Before Width: | Height: | Size: 5.6 KiB |
|
Before Width: | Height: | Size: 235 KiB |
|
Before Width: | Height: | Size: 16 KiB |
|
Before Width: | Height: | Size: 76 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 34 KiB |
|
Before Width: | Height: | Size: 37 KiB |
|
Before Width: | Height: | Size: 31 KiB |
|
Before Width: | Height: | Size: 13 KiB |
|
Before Width: | Height: | Size: 177 KiB |
|
Before Width: | Height: | Size: 269 KiB |
|
Before Width: | Height: | Size: 10 KiB |
|
Before Width: | Height: | Size: 29 KiB |
|
Before Width: | Height: | Size: 24 KiB |
|
Before Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 8.2 KiB |
|
Before Width: | Height: | Size: 43 KiB |